@robosystems/core 0.5.4 → 0.5.6

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.
@@ -14,7 +14,6 @@ const TOKEN_WARNING_CHECK_INTERVAL_MS = 30 * 1000; // 30 seconds - reduced for b
14
14
  const ACTIVITY_THROTTLE_MS = 1000; // 1 second
15
15
  const HEARTBEAT_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes - server validation heartbeat
16
16
  const REFRESH_COOLDOWN_MS = 60 * 1000; // 60 seconds - prevent duplicate background refreshes
17
- const LOGOUT_TIMEOUT_MS = 10 * 1000; // 10 seconds - timeout for logout operation
18
17
  const CACHE_VERSION = '1'; // Increment to invalidate all cached auth data
19
18
  // Debug logging helper
20
19
  const debugLog = (message, error) => {
@@ -63,7 +62,7 @@ export function AuthProvider({ children, apiUrl = process.env.NEXT_PUBLIC_ROBOSY
63
62
  }
64
63
  }
65
64
  }
66
- catch (error) {
65
+ catch (_a) {
67
66
  // User not authenticated anymore, clear cache
68
67
  setUser(null);
69
68
  if (typeof window !== 'undefined') {
@@ -92,7 +91,7 @@ export function AuthProvider({ children, apiUrl = process.env.NEXT_PUBLIC_ROBOSY
92
91
  }
93
92
  }
94
93
  }
95
- catch (error) {
94
+ catch (_a) {
96
95
  // User not authenticated, that's fine
97
96
  setUser(null);
98
97
  if (typeof window !== 'undefined') {
@@ -219,7 +218,7 @@ export function AuthProvider({ children, apiUrl = process.env.NEXT_PUBLIC_ROBOSY
219
218
  try {
220
219
  cachedUser = sessionStorage.getItem('auth_user_cache');
221
220
  }
222
- catch (error) {
221
+ catch (_a) {
223
222
  // Storage access error - proceed without cache
224
223
  }
225
224
  if (cachedUser) {
@@ -244,7 +243,7 @@ export function AuthProvider({ children, apiUrl = process.env.NEXT_PUBLIC_ROBOSY
244
243
  return;
245
244
  }
246
245
  }
247
- catch (error) {
246
+ catch (_b) {
248
247
  // Invalid cache, proceed with normal check
249
248
  try {
250
249
  sessionStorage.removeItem('auth_user_cache');
@@ -105,7 +105,7 @@ export class RoboSystemsAuthClient {
105
105
  const originalPatch = (_d = this.client.patch) === null || _d === void 0 ? void 0 : _d.bind(this.client);
106
106
  const originalDelete = (_e = this.client.delete) === null || _e === void 0 ? void 0 : _e.bind(this.client);
107
107
  // Helper to add JWT token to headers and handle 401 responses
108
- const wrapWithAuthAndErrorHandling = (originalMethod, methodName) => {
108
+ const wrapWithAuthAndErrorHandling = (originalMethod, _methodName) => {
109
109
  if (!originalMethod)
110
110
  return undefined;
111
111
  return async (options) => {
@@ -247,7 +247,7 @@ export class RoboSystemsAuthClient {
247
247
  });
248
248
  await Promise.race([logoutPromise, timeoutPromise]);
249
249
  }
250
- catch (error) {
250
+ catch (_a) {
251
251
  // Don't throw - continue with local cleanup even if backend fails
252
252
  }
253
253
  // Clear stored JWT token
@@ -260,7 +260,7 @@ export class RoboSystemsAuthClient {
260
260
  // Try to get current user - this should fail if logout worked
261
261
  await this.getCurrentUser();
262
262
  }
263
- catch (verifyError) {
263
+ catch (_b) {
264
264
  // This is expected - getCurrentUser should throw an error after logout
265
265
  }
266
266
  }
@@ -12,7 +12,7 @@ export function useUserHook(authClient, setUser) {
12
12
  setUser(user);
13
13
  return user;
14
14
  }
15
- catch (error) {
15
+ catch (_a) {
16
16
  setUser(null);
17
17
  return null;
18
18
  }
package/auth-core/sso.js CHANGED
@@ -2,7 +2,6 @@ import { useMemo } from 'react';
2
2
  import { RoboSystemsAuthClient } from './client';
3
3
  import { APP_CONFIGS } from './config';
4
4
  // Configuration constants
5
- const AUTH_CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
6
5
  const NAVIGATION_DELAY_MS = 100; // 100ms delay for navigation
7
6
  // Debug logging helper
8
7
  const debugLog = (message, error) => {
@@ -196,8 +195,7 @@ export class SSOManager {
196
195
  }
197
196
  if (cachedUser) {
198
197
  try {
199
- const userData = JSON.parse(cachedUser);
200
- const cacheAge = Date.now() - (userData.cached_at || 0);
198
+ JSON.parse(cachedUser);
201
199
  // REMOVED: Cache bypass logic that was skipping SSO flow
202
200
  // Always use proper SSO flow for cross-app authentication
203
201
  debugLog('Proceeding with full SSO flow for secure cross-app auth');
@@ -208,7 +206,7 @@ export class SSOManager {
208
206
  try {
209
207
  sessionStorage.removeItem('auth_user_cache');
210
208
  }
211
- catch (removeError) {
209
+ catch (_a) {
212
210
  // Storage error - continue silently
213
211
  }
214
212
  }
@@ -6,13 +6,6 @@ import { createContext, useCallback, useContext, useEffect, useState, } from 're
6
6
  export function createGraphContext() {
7
7
  return createContext(null);
8
8
  }
9
- // Helper to check if error is 403 Forbidden
10
- function is403Error(error) {
11
- var _a;
12
- return ((error === null || error === void 0 ? void 0 : error.status) === 403 ||
13
- ((_a = error === null || error === void 0 ? void 0 : error.response) === null || _a === void 0 ? void 0 : _a.status) === 403 ||
14
- (typeof error === 'object' && 'status' in error && error.status === 403));
15
- }
16
9
  // Generic provider factory
17
10
  export function createGraphProvider(Context) {
18
11
  return function GraphProvider({ children, initialGraphId, graphFilter, transformState, persistGraphSelection, }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robosystems/core",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "description": "Shared RoboSystems frontend core library (auth, contexts, task monitoring, UI components) for the RoboSystems Next.js apps",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -9,7 +9,5 @@ import Link from 'next/link';
9
9
  */
10
10
  export function CoverageCard({ item, hrefBase = '/research', }) {
11
11
  var _a;
12
- return (_jsx(Link, { href: `${hrefBase}/${item.ticker.toLowerCase()}`, className: "group block h-full", children: _jsxs("div", { className: "flex h-full flex-col overflow-hidden rounded-lg border border-gray-200 bg-white/80 shadow-lg backdrop-blur-sm transition-shadow duration-300 hover:shadow-xl dark:border-gray-700 dark:bg-zinc-950", children: [item.assets.thumbnail && (
13
- // eslint-disable-next-line @next/next/no-img-element
14
- _jsx("img", { src: item.assets.thumbnail, alt: item.title, className: "aspect-video w-full object-cover" })), _jsxs("div", { className: "flex flex-1 flex-col gap-2 p-5", children: [_jsxs("div", { className: "flex items-center gap-2 text-xs font-medium text-gray-500 dark:text-gray-400", children: [_jsx("span", { className: "rounded bg-cyan-500/10 px-2 py-0.5 font-semibold text-cyan-600 dark:text-cyan-400", children: item.ticker }), item.coverage_label && _jsx("span", { children: item.coverage_label }), _jsx("span", { className: "ml-auto", children: (_a = item.date) === null || _a === void 0 ? void 0 : _a.slice(0, 10) })] }), _jsx("h3", { className: "text-lg font-bold text-gray-900 group-hover:text-cyan-600 dark:text-white dark:group-hover:text-cyan-400", children: item.title }), _jsx("p", { className: "line-clamp-3 text-sm text-gray-600 dark:text-gray-300", children: item.summary }), item.history.length > 0 && (_jsxs("p", { className: "mt-auto pt-1 text-xs text-gray-400", children: ["+", item.history.length, " prior", ' ', item.history.length === 1 ? 'report' : 'reports'] }))] })] }) }));
12
+ return (_jsx(Link, { href: `${hrefBase}/${item.ticker.toLowerCase()}`, className: "group block h-full", children: _jsxs("div", { className: "flex h-full flex-col overflow-hidden rounded-lg border border-gray-200 bg-white/80 shadow-lg backdrop-blur-sm transition-shadow duration-300 hover:shadow-xl dark:border-gray-700 dark:bg-zinc-950", children: [item.assets.thumbnail && (_jsx("img", { src: item.assets.thumbnail, alt: item.title, className: "aspect-video w-full object-cover" })), _jsxs("div", { className: "flex flex-1 flex-col gap-2 p-5", children: [_jsxs("div", { className: "flex items-center gap-2 text-xs font-medium text-gray-500 dark:text-gray-400", children: [_jsx("span", { className: "rounded bg-cyan-500/10 px-2 py-0.5 font-semibold text-cyan-600 dark:text-cyan-400", children: item.ticker }), item.coverage_label && _jsx("span", { children: item.coverage_label }), _jsx("span", { className: "ml-auto", children: (_a = item.date) === null || _a === void 0 ? void 0 : _a.slice(0, 10) })] }), _jsx("h3", { className: "text-lg font-bold text-gray-900 group-hover:text-cyan-600 dark:text-white dark:group-hover:text-cyan-400", children: item.title }), _jsx("p", { className: "line-clamp-3 text-sm text-gray-600 dark:text-gray-300", children: item.summary }), item.history.length > 0 && (_jsxs("p", { className: "mt-auto pt-1 text-xs text-gray-400", children: ["+", item.history.length, " prior", ' ', item.history.length === 1 ? 'report' : 'reports'] }))] })] }) }));
15
13
  }
@@ -19,9 +19,7 @@ export function ResearchArticle({ item, briefMarkdown, }) {
19
19
  const body = (briefMarkdown || '').replace(/^#\s.*(\r?\n)+/, '');
20
20
  const ytId = youtubeId(item.youtube_url);
21
21
  const podcastYtId = youtubeId(item.podcast_youtube_url);
22
- return (_jsxs("article", { className: "mx-auto max-w-3xl", children: [_jsxs("div", { className: "mb-3 flex flex-wrap items-center gap-2 text-sm text-gray-500 dark:text-gray-400", children: [_jsxs("span", { className: "rounded bg-cyan-500/10 px-2 py-0.5 font-semibold text-cyan-600 dark:text-cyan-400", children: [item.company, " \u00B7 ", item.ticker] }), item.coverage_label && _jsx("span", { children: item.coverage_label }), _jsx("span", { children: (_a = item.date) === null || _a === void 0 ? void 0 : _a.slice(0, 10) })] }), _jsx("h1", { className: "mb-6 text-3xl font-bold text-gray-900 dark:text-white", children: item.title }), ytId ? (_jsx("div", { className: "mb-8 aspect-video w-full overflow-hidden rounded-xl bg-black", children: _jsx("iframe", { className: "h-full w-full", src: `https://www.youtube.com/embed/${ytId}`, title: item.title, loading: "lazy", allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share", allowFullScreen: true }) })) : (item.assets.video && (
23
- // eslint-disable-next-line jsx-a11y/media-has-caption
24
- _jsx("video", { controls: true, poster: item.assets.thumbnail, src: item.assets.video, className: "mb-8 aspect-video w-full rounded-xl bg-black" }))), (item.assets.podcast_mp3 || podcastYtId) && (_jsx("section", { className: "mb-8", children: item.assets.podcast_mp3 ? (_jsxs("div", { className: "rounded-xl border border-cyan-500/30 bg-cyan-50/60 p-4 dark:bg-gray-900/50", children: [_jsxs("div", { className: "mb-2 flex items-center justify-between gap-3", children: [_jsx("p", { className: "text-sm font-semibold text-cyan-600 dark:text-cyan-400", children: "\uD83C\uDF99 Listen \u2014 Q&A podcast" }), podcastYtId && (_jsx("a", { href: item.podcast_youtube_url, target: "_blank", rel: "noopener noreferrer", className: "shrink-0 text-xs text-cyan-600 hover:underline dark:text-cyan-400", children: "Watch on YouTube \u2197" }))] }), _jsx("audio", { controls: true, preload: "none", src: item.assets.podcast_mp3, className: "w-full" })] })) : (
22
+ return (_jsxs("article", { className: "mx-auto max-w-3xl", children: [_jsxs("div", { className: "mb-3 flex flex-wrap items-center gap-2 text-sm text-gray-500 dark:text-gray-400", children: [_jsxs("span", { className: "rounded bg-cyan-500/10 px-2 py-0.5 font-semibold text-cyan-600 dark:text-cyan-400", children: [item.company, " \u00B7 ", item.ticker] }), item.coverage_label && _jsx("span", { children: item.coverage_label }), _jsx("span", { children: (_a = item.date) === null || _a === void 0 ? void 0 : _a.slice(0, 10) })] }), _jsx("h1", { className: "mb-6 text-3xl font-bold text-gray-900 dark:text-white", children: item.title }), ytId ? (_jsx("div", { className: "mb-8 aspect-video w-full overflow-hidden rounded-xl bg-black", children: _jsx("iframe", { className: "h-full w-full", src: `https://www.youtube.com/embed/${ytId}`, title: item.title, loading: "lazy", allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share", allowFullScreen: true }) })) : (item.assets.video && (_jsx("video", { controls: true, poster: item.assets.thumbnail, src: item.assets.video, className: "mb-8 aspect-video w-full rounded-xl bg-black" }))), (item.assets.podcast_mp3 || podcastYtId) && (_jsx("section", { className: "mb-8", children: item.assets.podcast_mp3 ? (_jsxs("div", { className: "rounded-xl border border-cyan-500/30 bg-cyan-50/60 p-4 dark:bg-gray-900/50", children: [_jsxs("div", { className: "mb-2 flex items-center justify-between gap-3", children: [_jsx("p", { className: "text-sm font-semibold text-cyan-600 dark:text-cyan-400", children: "\uD83C\uDF99 Listen \u2014 Q&A podcast" }), podcastYtId && (_jsx("a", { href: item.podcast_youtube_url, target: "_blank", rel: "noopener noreferrer", className: "shrink-0 text-xs text-cyan-600 hover:underline dark:text-cyan-400", children: "Watch on YouTube \u2197" }))] }), _jsx("audio", { controls: true, preload: "none", src: item.assets.podcast_mp3, className: "w-full" })] })) : (
25
23
  // no MP3 yet — fall back to the YouTube video player
26
24
  _jsxs(_Fragment, { children: [_jsx("h2", { className: "mb-3 text-xl font-bold text-gray-900 dark:text-white", children: "Listen \u2014 Q&A podcast" }), _jsx("div", { className: "aspect-video w-full overflow-hidden rounded-xl bg-black", children: _jsx("iframe", { className: "h-full w-full", src: `https://www.youtube.com/embed/${podcastYtId}`, title: `${item.title} — Q&A podcast`, loading: "lazy", allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share", allowFullScreen: true }) })] })) })), body && (_jsx("div", { className: "prose prose-lg prose-headings:font-heading prose-headings:font-bold prose-headings:text-gray-900 dark:prose-headings:text-white prose-p:text-gray-700 dark:prose-p:text-gray-300 prose-p:leading-relaxed prose-a:text-cyan-600 dark:prose-a:text-cyan-400 prose-a:no-underline hover:prose-a:text-cyan-500 dark:hover:prose-a:text-cyan-300 prose-strong:text-gray-900 dark:prose-strong:text-white prose-strong:font-semibold prose-em:text-gray-700 dark:prose-em:text-gray-300 prose-code:text-cyan-700 dark:prose-code:text-cyan-400 prose-code:bg-gray-100 dark:prose-code:bg-gray-800 prose-code:px-2 prose-code:py-1 prose-code:rounded prose-pre:bg-gray-900 prose-pre:border prose-pre:border-gray-800 prose-blockquote:border-l-cyan-500 prose-blockquote:text-gray-600 dark:prose-blockquote:text-gray-400 prose-blockquote:italic prose-ul:text-gray-700 dark:prose-ul:text-gray-300 prose-ol:text-gray-700 dark:prose-ol:text-gray-300 prose-li:marker:text-cyan-500 prose-hr:border-gray-200 dark:prose-hr:border-gray-800 prose-table:border-gray-300 dark:prose-table:border-gray-700 prose-th:bg-gray-100 dark:prose-th:bg-gray-900 prose-th:text-gray-900 dark:prose-th:text-white prose-td:text-gray-700 dark:prose-td:text-gray-300 max-w-none", children: _jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], children: body }) })), _jsx(CoverageHistory, { history: item.history }), _jsxs("footer", { className: "mt-12 border-t border-gray-200 pt-6 dark:border-gray-800", children: [_jsx("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: "Audio & music produced with ElevenLabs." }), _jsxs("a", { href: "https://elevenlabs.io/startup-grants", target: "_blank", rel: "noopener noreferrer", "aria-label": "Backed by the ElevenLabs Grants program", className: "mt-3 inline-block", children: [_jsx("img", { src: "/images/logos/elevenlabs-grants.webp", alt: "Backed by the ElevenLabs Grants program", width: 200, className: "h-auto dark:hidden" }), _jsx("img", { src: "/images/logos/elevenlabs-grants-white.webp", alt: "Backed by the ElevenLabs Grants program", width: 200, className: "hidden h-auto dark:block" })] }), _jsxs("p", { className: "mt-2 text-xs text-gray-400 dark:text-gray-500", children: ["Using ElevenLabs yourself? Our", ' ', _jsx("a", { href: "https://try.elevenlabs.io/v9z3wzm97gk3", target: "_blank", rel: "noopener noreferrer", className: "hover:underline", children: "referral link" }), ' ', "costs you nothing extra and supports this research."] })] })] }));
27
25
  }
@@ -72,17 +72,9 @@ export class OperationMonitor {
72
72
  if (this.operationResults.has(operationId)) {
73
73
  return this.operationResults.get(operationId);
74
74
  }
75
- try {
76
- const config = client.getConfig();
77
- const baseUrl = config.baseUrl || 'http://localhost:8000';
78
- // This would need to be implemented as a sync call or return cached data only
79
- // For now, just return cached results
80
- return null;
81
- }
82
- catch (error) {
83
- console.error('Failed to get operation status:', error);
84
- return null;
85
- }
75
+ // Fetching an uncached status would need a synchronous call; until that
76
+ // exists this returns cached results only.
77
+ return null;
86
78
  }
87
79
  /**
88
80
  * Clean up operation monitoring resources
@@ -12,11 +12,18 @@ interface EmptyStateProps {
12
12
  action?: ReactNode;
13
13
  /** Override the container spacing (default `py-12`). */
14
14
  className?: string;
15
+ /**
16
+ * Heading level for the title. Defaults to `2`, which is correct when the
17
+ * empty state sits directly inside a page whose title is the `<h1>` — the
18
+ * common case. Pass `3` (or deeper) when it is nested under a section that
19
+ * already has its own heading, so the document outline stays contiguous.
20
+ */
21
+ headingLevel?: 2 | 3 | 4;
15
22
  }
16
23
  /**
17
24
  * The shared empty state: a muted icon, a title, an optional description, and an
18
25
  * optional action — centered. Render it inside whatever container the page uses
19
26
  * (often a `<Card>`); this component is just the centered inner block.
20
27
  */
21
- export declare function EmptyState({ icon: Icon, title, description, action, className, }: EmptyStateProps): import("react").JSX.Element;
28
+ export declare function EmptyState({ icon: Icon, title, description, action, className, headingLevel, }: EmptyStateProps): import("react").JSX.Element;
22
29
  export {};
@@ -5,6 +5,7 @@ import { twMerge } from 'tailwind-merge';
5
5
  * optional action — centered. Render it inside whatever container the page uses
6
6
  * (often a `<Card>`); this component is just the centered inner block.
7
7
  */
8
- export function EmptyState({ icon: Icon, title, description, action, className, }) {
9
- return (_jsxs("div", { className: twMerge('py-12 text-center', className), children: [_jsx(Icon, { className: "mx-auto h-12 w-12 text-gray-400", "aria-hidden": "true" }), _jsx("h3", { className: "mt-2 text-sm font-medium text-gray-900 dark:text-white", children: title }), description && (_jsx("div", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: description })), action && _jsx("div", { className: "mt-6", children: action })] }));
8
+ export function EmptyState({ icon: Icon, title, description, action, className, headingLevel = 2, }) {
9
+ const Heading = `h${headingLevel}`;
10
+ return (_jsxs("div", { className: twMerge('py-12 text-center', className), children: [_jsx(Icon, { className: "mx-auto h-12 w-12 text-gray-400", "aria-hidden": "true" }), _jsx(Heading, { className: "mt-2 text-sm font-medium text-gray-900 dark:text-white", children: title }), description && (_jsx("div", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: description })), action && _jsx("div", { className: "mt-6", children: action })] }));
10
11
  }
@@ -41,7 +41,7 @@ export const ApiKeysCard = ({ theme, className = '', }) => {
41
41
  });
42
42
  setApiKeys(keys);
43
43
  }
44
- catch (err) {
44
+ catch (_b) {
45
45
  setError('Failed to load API keys. Please try again.');
46
46
  }
47
47
  finally {
@@ -80,7 +80,7 @@ export const ApiKeysCard = ({ theme, className = '', }) => {
80
80
  });
81
81
  await fetchApiKeys(); // Refresh the list
82
82
  }
83
- catch (err) {
83
+ catch (_a) {
84
84
  setError('Failed to revoke API key. Please try again.');
85
85
  }
86
86
  };
@@ -21,7 +21,7 @@ export const CreateApiKeyModal = ({ isOpen, onClose, onCreateKey, theme, }) => {
21
21
  });
22
22
  setNewApiKey(result);
23
23
  }
24
- catch (err) {
24
+ catch (_a) {
25
25
  setError('Failed to create API key. Please try again.');
26
26
  }
27
27
  finally {
@@ -16,7 +16,6 @@ export function CoreNavbar({ appName, currentApp, apiUrl = process.env.NEXT_PUBL
16
16
  const isDesktop = useMediaQuery('(min-width: 1024px)');
17
17
  const { user } = useUser();
18
18
  const { logout } = useAuth();
19
- const altText = logoAltText || `${appName} Logo`;
20
19
  function handleToggleSidebar() {
21
20
  if (isDesktop) {
22
21
  sidebar.desktop.toggle();
@@ -30,5 +30,5 @@ export function LandingFooter({ tagline, productLinks, contactModal: ContactModa
30
30
  return (_jsx("li", { children: _jsx(Link, Object.assign({ href: cfg.url }, (isCurrent
31
31
  ? {}
32
32
  : { target: '_blank', rel: 'noopener noreferrer' }), { className: linkClass, children: cfg.displayName })) }, app));
33
- }) })] }), _jsxs("div", { children: [_jsx("h3", { className: headingClass, children: "Company" }), _jsxs("ul", { className: "space-y-2 text-sm", children: [_jsx("li", { children: _jsx(Link, Object.assign({ href: `${companyBase}/research` }, companyLinkProps, { className: linkClass, children: "Research" })) }), _jsx("li", { children: _jsx(Link, { href: "https://holon.robosystems.ai", target: "_blank", rel: "noopener noreferrer", className: linkClass, children: "Holon Viewer" }) }), _jsx("li", { children: _jsx(Link, Object.assign({ href: `${companyBase}/blog` }, companyLinkProps, { className: linkClass, children: "Blog" })) }), _jsx("li", { children: _jsx(Link, Object.assign({ href: `${companyBase}/pages/privacy` }, companyLinkProps, { className: linkClass, children: "Privacy" })) }), _jsx("li", { children: _jsx(Link, Object.assign({ href: `${companyBase}/pages/terms` }, companyLinkProps, { className: linkClass, children: "Terms" })) }), _jsx("li", { children: _jsx(Link, { href: "https://app.vanta.com/robosystems.ai/trust/lzitnsl1mo27b6zahy0ksy", target: "_blank", rel: "noopener noreferrer", className: linkClass, children: "Trust Center" }) }), ContactModal && (_jsx("li", { children: _jsx("button", { onClick: () => setShowContact(true), className: linkClass, children: "Contact" }) }))] })] })] }), _jsx("div", { className: "mt-8 border-t border-gray-800 pt-8 text-center text-sm text-gray-400", children: _jsxs("p", { children: ["\u00A9 ", new Date().getFullYear(), " RFS LLC. All rights reserved."] }) })] }), ContactModal && (_jsx(ContactModal, { isOpen: showContact, onClose: () => setShowContact(false) }))] }));
33
+ }) })] }), _jsxs("div", { children: [_jsx("h3", { className: headingClass, children: "Company" }), _jsxs("ul", { className: "space-y-2 text-sm", children: [_jsx("li", { children: _jsx(Link, Object.assign({ href: `${companyBase}/research` }, companyLinkProps, { className: linkClass, children: "Research" })) }), _jsx("li", { children: _jsx(Link, { href: "https://holon.robosystems.ai", target: "_blank", rel: "noopener noreferrer", className: linkClass, children: "Holon Viewer" }) }), _jsx("li", { children: _jsx(Link, Object.assign({ href: `${companyBase}/blog` }, companyLinkProps, { className: linkClass, children: "Blog" })) }), _jsx("li", { children: _jsx(Link, Object.assign({ href: `${companyBase}/pages/privacy` }, companyLinkProps, { className: linkClass, children: "Privacy" })) }), _jsx("li", { children: _jsx(Link, Object.assign({ href: `${companyBase}/pages/terms` }, companyLinkProps, { className: linkClass, children: "Terms" })) }), _jsx("li", { children: _jsx(Link, { href: "https://trust.robosystems.ai", target: "_blank", rel: "noopener noreferrer", className: linkClass, children: "Trust Center" }) }), ContactModal && (_jsx("li", { children: _jsx("button", { onClick: () => setShowContact(true), className: linkClass, children: "Contact" }) }))] })] })] }), _jsx("div", { className: "mt-8 border-t border-gray-800 pt-8 text-center text-sm text-gray-400", children: _jsxs("p", { children: ["\u00A9 ", new Date().getFullYear(), " RFS LLC. All rights reserved."] }) })] }), ContactModal && (_jsx(ContactModal, { isOpen: showContact, onClose: () => setShowContact(false) }))] }));
34
34
  }