@robosystems/core 0.3.0

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.
Files changed (249) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +252 -0
  3. package/actions/entity-actions.d.ts +8 -0
  4. package/actions/entity-actions.js +16 -0
  5. package/actions/graph-actions.d.ts +3 -0
  6. package/actions/graph-actions.js +13 -0
  7. package/auth-components/AppSwitcher.d.ts +6 -0
  8. package/auth-components/AppSwitcher.js +28 -0
  9. package/auth-components/AuthGuard.d.ts +7 -0
  10. package/auth-components/AuthGuard.js +31 -0
  11. package/auth-components/AuthProvider.d.ts +9 -0
  12. package/auth-components/AuthProvider.js +565 -0
  13. package/auth-components/SessionWarningDialog.d.ts +1 -0
  14. package/auth-components/SessionWarningDialog.js +51 -0
  15. package/auth-components/SignInForm.d.ts +20 -0
  16. package/auth-components/SignInForm.js +139 -0
  17. package/auth-components/SignUpForm.d.ts +15 -0
  18. package/auth-components/SignUpForm.js +167 -0
  19. package/auth-components/TurnstileWidget.d.ts +99 -0
  20. package/auth-components/TurnstileWidget.js +224 -0
  21. package/auth-components/index.d.ts +6 -0
  22. package/auth-components/index.js +6 -0
  23. package/auth-core/cleanup.d.ts +44 -0
  24. package/auth-core/cleanup.js +157 -0
  25. package/auth-core/client.d.ts +121 -0
  26. package/auth-core/client.js +767 -0
  27. package/auth-core/config.d.ts +19 -0
  28. package/auth-core/config.js +56 -0
  29. package/auth-core/hooks.d.ts +19 -0
  30. package/auth-core/hooks.js +63 -0
  31. package/auth-core/index.d.ts +6 -0
  32. package/auth-core/index.js +6 -0
  33. package/auth-core/sso.d.ts +42 -0
  34. package/auth-core/sso.js +281 -0
  35. package/auth-core/token-storage.d.ts +58 -0
  36. package/auth-core/token-storage.js +177 -0
  37. package/auth-core/types.d.ts +145 -0
  38. package/auth-core/types.js +1 -0
  39. package/components/EntitySelector.d.ts +44 -0
  40. package/components/EntitySelector.js +64 -0
  41. package/components/EntitySelectorCore.d.ts +45 -0
  42. package/components/EntitySelectorCore.js +67 -0
  43. package/components/GraphSelectorCore.d.ts +21 -0
  44. package/components/GraphSelectorCore.js +39 -0
  45. package/components/PageLayout.d.ts +8 -0
  46. package/components/PageLayout.js +5 -0
  47. package/components/RepositoryGuard.d.ts +68 -0
  48. package/components/RepositoryGuard.js +91 -0
  49. package/components/console/ConsoleContent.d.ts +4 -0
  50. package/components/console/ConsoleContent.js +612 -0
  51. package/components/console/ConsoleMarkdown.d.ts +11 -0
  52. package/components/console/ConsoleMarkdown.js +49 -0
  53. package/components/console/ProgressiveText.d.ts +6 -0
  54. package/components/console/ProgressiveText.js +21 -0
  55. package/components/console/graphAwareConfig.d.ts +70 -0
  56. package/components/console/graphAwareConfig.js +411 -0
  57. package/components/console/index.d.ts +6 -0
  58. package/components/console/index.js +4 -0
  59. package/components/console/types.d.ts +84 -0
  60. package/components/console/types.js +1 -0
  61. package/components/graph-filters.d.ts +75 -0
  62. package/components/graph-filters.js +111 -0
  63. package/components/index.d.ts +10 -0
  64. package/components/index.js +9 -0
  65. package/components/repositories/ActiveSubscriptions.d.ts +26 -0
  66. package/components/repositories/ActiveSubscriptions.js +103 -0
  67. package/components/repositories/BrowseRepositories.d.ts +11 -0
  68. package/components/repositories/BrowseRepositories.js +184 -0
  69. package/components/repositories/index.d.ts +2 -0
  70. package/components/repositories/index.js +2 -0
  71. package/components/search/SearchContent.d.ts +4 -0
  72. package/components/search/SearchContent.js +168 -0
  73. package/components/search/index.d.ts +2 -0
  74. package/components/search/index.js +1 -0
  75. package/components/search/types.d.ts +15 -0
  76. package/components/search/types.js +1 -0
  77. package/contexts/entity-context.d.ts +28 -0
  78. package/contexts/entity-context.js +89 -0
  79. package/contexts/graph-context.d.ts +27 -0
  80. package/contexts/graph-context.js +128 -0
  81. package/contexts/index.d.ts +5 -0
  82. package/contexts/index.js +5 -0
  83. package/contexts/org-context.d.ts +25 -0
  84. package/contexts/org-context.js +64 -0
  85. package/contexts/service-offerings-context.d.ts +45 -0
  86. package/contexts/service-offerings-context.js +98 -0
  87. package/contexts/sidebar-context.d.ts +18 -0
  88. package/contexts/sidebar-context.js +44 -0
  89. package/hooks/index.d.ts +6 -0
  90. package/hooks/index.js +6 -0
  91. package/hooks/use-api-error.d.ts +3 -0
  92. package/hooks/use-api-error.js +24 -0
  93. package/hooks/use-media-query.d.ts +1 -0
  94. package/hooks/use-media-query.js +21 -0
  95. package/hooks/use-streaming-query.d.ts +22 -0
  96. package/hooks/use-streaming-query.js +142 -0
  97. package/hooks/use-toast.d.ts +37 -0
  98. package/hooks/use-toast.js +117 -0
  99. package/hooks/use-user-limits.d.ts +12 -0
  100. package/hooks/use-user-limits.js +73 -0
  101. package/hooks/use-user.d.ts +11 -0
  102. package/hooks/use-user.js +39 -0
  103. package/index.d.ts +29 -0
  104. package/index.js +77 -0
  105. package/lib/entity-cookie.d.ts +10 -0
  106. package/lib/entity-cookie.js +38 -0
  107. package/lib/graph-cookie.d.ts +11 -0
  108. package/lib/graph-cookie.js +62 -0
  109. package/lib/graph-tiers.d.ts +41 -0
  110. package/lib/graph-tiers.js +107 -0
  111. package/lib/index.d.ts +3 -0
  112. package/lib/index.js +3 -0
  113. package/lib/sidebar-cookie.d.ts +11 -0
  114. package/lib/sidebar-cookie.js +42 -0
  115. package/library/colors.d.ts +4 -0
  116. package/library/colors.js +41 -0
  117. package/library/components/ClassificationPicker.d.ts +8 -0
  118. package/library/components/ClassificationPicker.js +55 -0
  119. package/library/components/ElementBrowser.d.ts +11 -0
  120. package/library/components/ElementBrowser.js +106 -0
  121. package/library/components/ElementDetail.d.ts +7 -0
  122. package/library/components/ElementDetail.js +97 -0
  123. package/library/components/LibraryHierarchy.d.ts +13 -0
  124. package/library/components/LibraryHierarchy.js +380 -0
  125. package/library/components/TaxonomySidebar.d.ts +6 -0
  126. package/library/components/TaxonomySidebar.js +45 -0
  127. package/library/index.d.ts +8 -0
  128. package/library/index.js +7 -0
  129. package/package.json +37 -0
  130. package/research/CoverageCard.d.ts +12 -0
  131. package/research/CoverageCard.js +15 -0
  132. package/research/CoverageGrid.d.ts +6 -0
  133. package/research/CoverageGrid.js +9 -0
  134. package/research/CoverageHistory.d.ts +5 -0
  135. package/research/CoverageHistory.js +7 -0
  136. package/research/ResearchArticle.d.ts +15 -0
  137. package/research/ResearchArticle.js +26 -0
  138. package/research/catalog.d.ts +14 -0
  139. package/research/catalog.js +42 -0
  140. package/research/index.d.ts +6 -0
  141. package/research/index.js +9 -0
  142. package/research/types.d.ts +38 -0
  143. package/research/types.js +4 -0
  144. package/task-monitoring/hooks.d.ts +26 -0
  145. package/task-monitoring/hooks.js +126 -0
  146. package/task-monitoring/index.d.ts +5 -0
  147. package/task-monitoring/index.js +7 -0
  148. package/task-monitoring/operationErrors.d.ts +82 -0
  149. package/task-monitoring/operationErrors.js +251 -0
  150. package/task-monitoring/operationHooks.d.ts +117 -0
  151. package/task-monitoring/operationHooks.js +536 -0
  152. package/task-monitoring/operationMonitor.d.ts +78 -0
  153. package/task-monitoring/operationMonitor.js +200 -0
  154. package/task-monitoring/operationTypes.d.ts +236 -0
  155. package/task-monitoring/operationTypes.js +60 -0
  156. package/task-monitoring/taskMonitor.d.ts +14 -0
  157. package/task-monitoring/taskMonitor.js +132 -0
  158. package/task-monitoring/types.d.ts +31 -0
  159. package/task-monitoring/types.js +1 -0
  160. package/theme/flowbite-theme.d.ts +758 -0
  161. package/theme/flowbite-theme.js +765 -0
  162. package/theme/index.d.ts +1 -0
  163. package/theme/index.js +1 -0
  164. package/types/entity.d.ts +19 -0
  165. package/types/index.d.ts +2 -0
  166. package/types/index.js +1 -0
  167. package/types/user.d.ts +6 -0
  168. package/ui-components/ConfirmModal.d.ts +41 -0
  169. package/ui-components/ConfirmModal.js +19 -0
  170. package/ui-components/EmptyState.d.ts +22 -0
  171. package/ui-components/EmptyState.js +10 -0
  172. package/ui-components/LoadingState.d.ts +27 -0
  173. package/ui-components/LoadingState.js +12 -0
  174. package/ui-components/Logo.d.ts +28 -0
  175. package/ui-components/Logo.js +95 -0
  176. package/ui-components/Spinner.d.ts +37 -0
  177. package/ui-components/Spinner.js +48 -0
  178. package/ui-components/StatCard.d.ts +21 -0
  179. package/ui-components/StatCard.js +10 -0
  180. package/ui-components/api-keys/ApiKeyDisplay.d.ts +13 -0
  181. package/ui-components/api-keys/ApiKeyDisplay.js +7 -0
  182. package/ui-components/api-keys/ApiKeyTable.d.ts +9 -0
  183. package/ui-components/api-keys/ApiKeyTable.js +17 -0
  184. package/ui-components/api-keys/ApiKeysCard.d.ts +6 -0
  185. package/ui-components/api-keys/ApiKeysCard.js +97 -0
  186. package/ui-components/api-keys/CreateApiKeyModal.d.ts +11 -0
  187. package/ui-components/api-keys/CreateApiKeyModal.js +47 -0
  188. package/ui-components/api-keys/SecureApiKeyField.d.ts +13 -0
  189. package/ui-components/api-keys/SecureApiKeyField.js +64 -0
  190. package/ui-components/api-keys/index.d.ts +5 -0
  191. package/ui-components/api-keys/index.js +5 -0
  192. package/ui-components/chat/ChatHeader.d.ts +12 -0
  193. package/ui-components/chat/ChatHeader.js +5 -0
  194. package/ui-components/chat/ChatInputArea.d.ts +16 -0
  195. package/ui-components/chat/ChatInputArea.js +9 -0
  196. package/ui-components/chat/ChatMessage.d.ts +7 -0
  197. package/ui-components/chat/ChatMessage.js +24 -0
  198. package/ui-components/chat/DeepResearchToggle.d.ts +8 -0
  199. package/ui-components/chat/DeepResearchToggle.js +13 -0
  200. package/ui-components/chat/index.d.ts +9 -0
  201. package/ui-components/chat/index.js +8 -0
  202. package/ui-components/chat/types.d.ts +23 -0
  203. package/ui-components/chat/types.js +51 -0
  204. package/ui-components/forms/PasswordRequirements.d.ts +10 -0
  205. package/ui-components/forms/PasswordRequirements.js +15 -0
  206. package/ui-components/forms/SettingsCard.d.ts +11 -0
  207. package/ui-components/forms/SettingsCard.js +5 -0
  208. package/ui-components/forms/SettingsFormField.d.ts +18 -0
  209. package/ui-components/forms/SettingsFormField.js +17 -0
  210. package/ui-components/forms/StatusAlert.d.ts +8 -0
  211. package/ui-components/forms/StatusAlert.js +7 -0
  212. package/ui-components/forms/index.d.ts +4 -0
  213. package/ui-components/forms/index.js +4 -0
  214. package/ui-components/index.d.ts +13 -0
  215. package/ui-components/index.js +18 -0
  216. package/ui-components/layout/CoreNavbar.d.ts +14 -0
  217. package/ui-components/layout/CoreNavbar.js +53 -0
  218. package/ui-components/layout/CoreSidebar.d.ts +28 -0
  219. package/ui-components/layout/CoreSidebar.js +62 -0
  220. package/ui-components/layout/LandingFooter.d.ts +28 -0
  221. package/ui-components/layout/LandingFooter.js +34 -0
  222. package/ui-components/layout/PageContainer.d.ts +8 -0
  223. package/ui-components/layout/PageContainer.js +17 -0
  224. package/ui-components/layout/PageHeader.d.ts +23 -0
  225. package/ui-components/layout/PageHeader.js +12 -0
  226. package/ui-components/layout/SettingsContainer.d.ts +10 -0
  227. package/ui-components/layout/SettingsContainer.js +9 -0
  228. package/ui-components/layout/ThemeToggle.d.ts +4 -0
  229. package/ui-components/layout/ThemeToggle.js +6 -0
  230. package/ui-components/layout/index.d.ts +7 -0
  231. package/ui-components/layout/index.js +7 -0
  232. package/ui-components/settings/GeneralInformationCard.d.ts +12 -0
  233. package/ui-components/settings/GeneralInformationCard.js +72 -0
  234. package/ui-components/settings/PasswordInformationCard.d.ts +10 -0
  235. package/ui-components/settings/PasswordInformationCard.js +167 -0
  236. package/ui-components/settings/SettingsPageHeader.d.ts +7 -0
  237. package/ui-components/settings/SettingsPageHeader.js +6 -0
  238. package/ui-components/settings/index.d.ts +3 -0
  239. package/ui-components/settings/index.js +3 -0
  240. package/ui-components/support/SupportModal.d.ts +15 -0
  241. package/ui-components/support/SupportModal.js +74 -0
  242. package/ui-components/support/index.d.ts +2 -0
  243. package/ui-components/support/index.js +1 -0
  244. package/ui-components/types/index.d.ts +39 -0
  245. package/ui-components/types/index.js +1 -0
  246. package/utils/index.d.ts +31 -0
  247. package/utils/index.js +38 -0
  248. package/utils/turnstile-config.d.ts +11 -0
  249. package/utils/turnstile-config.js +19 -0
@@ -0,0 +1,47 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { Button, Label, Modal, ModalBody, ModalFooter, ModalHeader, } from 'flowbite-react';
4
+ import { useState } from 'react';
5
+ import { Spinner } from '../Spinner';
6
+ import { SettingsFormField } from '../forms/SettingsFormField';
7
+ import { StatusAlert } from '../forms/StatusAlert';
8
+ import { ApiKeyDisplay } from './ApiKeyDisplay';
9
+ export const CreateApiKeyModal = ({ isOpen, onClose, onCreateKey, theme, }) => {
10
+ const [isCreating, setIsCreating] = useState(false);
11
+ const [newApiKey, setNewApiKey] = useState(null);
12
+ const [keyName, setKeyName] = useState('');
13
+ const [error, setError] = useState(null);
14
+ const handleSubmit = async (e) => {
15
+ e.preventDefault();
16
+ setIsCreating(true);
17
+ setError(null);
18
+ try {
19
+ const result = await onCreateKey({
20
+ name: keyName,
21
+ });
22
+ setNewApiKey(result);
23
+ }
24
+ catch (err) {
25
+ setError('Failed to create API key. Please try again.');
26
+ }
27
+ finally {
28
+ setIsCreating(false);
29
+ }
30
+ };
31
+ const handleCloseModal = () => {
32
+ onClose();
33
+ setKeyName('');
34
+ setNewApiKey(null);
35
+ setError(null);
36
+ };
37
+ const formatDate = (date) => {
38
+ if (!date)
39
+ return 'Never';
40
+ return new Date(date).toLocaleDateString('en-US', {
41
+ year: 'numeric',
42
+ month: 'short',
43
+ day: 'numeric',
44
+ });
45
+ };
46
+ return (_jsxs(Modal, { theme: theme === null || theme === void 0 ? void 0 : theme.modal, show: isOpen, onClose: handleCloseModal, children: [_jsx(ModalHeader, { children: "Create API Key" }), _jsx(ModalBody, { children: newApiKey ? (_jsxs("div", { children: [_jsx(StatusAlert, { type: "success", message: "Your API key has been created.", theme: theme === null || theme === void 0 ? void 0 : theme.alert }), _jsxs("div", { className: "mb-4 space-y-4", children: [_jsx(ApiKeyDisplay, { label: "ROBOSYSTEMS_API_KEY", value: newApiKey.key, keyId: newApiKey.id, theme: theme }), _jsx("p", { className: "text-sm font-medium text-red-600 dark:text-red-400", children: "\u26A0\uFE0F Important: Save this API key somewhere safe. For security reasons, you cannot view it again after closing this dialog." })] }), _jsxs("div", { className: "mb-2", children: [_jsx(Label, { theme: theme === null || theme === void 0 ? void 0 : theme.label, htmlFor: "keyDetails", children: "Key Details" }), _jsxs("div", { className: "mt-2 space-y-2 rounded-lg border border-zinc-200 bg-zinc-50 p-3 dark:border-zinc-700 dark:bg-zinc-800", children: [_jsxs("div", { className: "flex justify-between", children: [_jsx("span", { className: "text-sm font-medium text-zinc-500 dark:text-zinc-400", children: "Name:" }), _jsx("span", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: newApiKey.name })] }), _jsxs("div", { className: "flex justify-between", children: [_jsx("span", { className: "text-sm font-medium text-zinc-500 dark:text-zinc-400", children: "Created:" }), _jsx("span", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: formatDate(newApiKey.createdAt) })] }), _jsxs("div", { className: "flex justify-between", children: [_jsx("span", { className: "text-sm font-medium text-zinc-500 dark:text-zinc-400", children: "Status:" }), _jsx("span", { className: "text-sm font-semibold text-zinc-900 dark:text-zinc-100", children: "Active" })] })] })] })] })) : (_jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [_jsx(SettingsFormField, { id: "keyName", label: "API Key Name", placeholder: "My API Key", value: keyName, onChange: (e) => setKeyName(e.target.value), required: true, theme: theme }), _jsx("p", { className: "text-sm text-zinc-500 dark:text-zinc-400", children: "Give your API key a memorable name to identify it later" }), _jsx("div", { className: "bg-primary-50 dark:bg-primary-900/30 rounded-lg p-3", children: _jsxs("p", { className: "text-primary-800 dark:text-primary-300 text-sm", children: [_jsx("strong", { children: "Note:" }), " API keys do not expire by date. Keys that haven't been used for 90 days will be automatically deactivated for security."] }) }), error && (_jsx(StatusAlert, { type: "error", message: error, theme: theme === null || theme === void 0 ? void 0 : theme.alert }))] })) }), _jsx(ModalFooter, { children: newApiKey ? (_jsx(Button, { theme: theme === null || theme === void 0 ? void 0 : theme.button, color: "blue", onClick: handleCloseModal, children: "Done" })) : (_jsxs(_Fragment, { children: [_jsx(Button, { theme: theme === null || theme === void 0 ? void 0 : theme.button, color: "gray", onClick: handleCloseModal, children: "Cancel" }), _jsx(Button, { theme: theme === null || theme === void 0 ? void 0 : theme.button, color: "primary", onClick: handleSubmit, disabled: isCreating || !keyName, children: isCreating ? (_jsx(Spinner, { size: "sm", className: "text-white" })) : ('Create API Key') })] })) })] }));
47
+ };
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ export interface SecureApiKeyFieldProps {
3
+ apiKey: string;
4
+ keyId: string;
5
+ keyName?: string;
6
+ className?: string;
7
+ showLabel?: boolean;
8
+ label?: string;
9
+ onCopy?: () => void;
10
+ onReveal?: () => void;
11
+ onDownload?: () => void;
12
+ }
13
+ export declare const SecureApiKeyField: React.FC<SecureApiKeyFieldProps>;
@@ -0,0 +1,64 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Button, TextInput, Tooltip } from 'flowbite-react';
4
+ import { useState } from 'react';
5
+ import { HiCheckCircle, HiClipboardCopy, HiDownload, HiEye, HiEyeOff, } from 'react-icons/hi';
6
+ export const SecureApiKeyField = ({ apiKey, keyId, keyName = 'API Key', className = '', showLabel = false, label = 'API Key', onCopy, onReveal, onDownload, }) => {
7
+ const [isRevealed, setIsRevealed] = useState(false);
8
+ const [copyStatus, setCopyStatus] = useState('idle');
9
+ const [revealCount, setRevealCount] = useState(0);
10
+ const maskedKey = `${keyId.substring(0, 8)}${'•'.repeat(24)}`;
11
+ const handleReveal = () => {
12
+ if (revealCount >= 3) {
13
+ // Log excessive reveal attempts for security monitoring
14
+ console.warn(`Excessive API key reveals for key ${keyId}`);
15
+ }
16
+ setIsRevealed(!isRevealed);
17
+ setRevealCount((prev) => prev + 1);
18
+ // Auto-hide after 5 seconds for security
19
+ if (!isRevealed) {
20
+ setTimeout(() => {
21
+ setIsRevealed(false);
22
+ }, 5000);
23
+ }
24
+ onReveal === null || onReveal === void 0 ? void 0 : onReveal();
25
+ };
26
+ const handleCopy = async () => {
27
+ try {
28
+ await navigator.clipboard.writeText(apiKey);
29
+ setCopyStatus('copied');
30
+ // Reset copy status after 2 seconds
31
+ setTimeout(() => {
32
+ setCopyStatus('idle');
33
+ }, 2000);
34
+ onCopy === null || onCopy === void 0 ? void 0 : onCopy();
35
+ }
36
+ catch (error) {
37
+ console.error('Failed to copy API key:', error);
38
+ }
39
+ };
40
+ const handleDownload = () => {
41
+ const content = `API Key: ${keyName}
42
+ Key ID: ${keyId}
43
+ Key Value: ${apiKey}
44
+
45
+ IMPORTANT: Keep this file secure and do not share it with anyone.
46
+ Delete this file after storing the key in a secure location.
47
+ `;
48
+ const blob = new Blob([content], { type: 'text/plain' });
49
+ const url = URL.createObjectURL(blob);
50
+ const a = document.createElement('a');
51
+ a.href = url;
52
+ a.download = `api-key-${keyId.substring(0, 8)}.txt`;
53
+ document.body.appendChild(a);
54
+ a.click();
55
+ document.body.removeChild(a);
56
+ URL.revokeObjectURL(url);
57
+ onDownload === null || onDownload === void 0 ? void 0 : onDownload();
58
+ };
59
+ return (_jsxs("div", { className: className, children: [showLabel && (_jsx("label", { className: "mb-2 block text-sm font-medium text-zinc-900 dark:text-zinc-100", children: label })), _jsxs("div", { className: "relative flex items-center", children: [_jsx("div", { className: "relative w-full overflow-hidden", children: _jsx(TextInput, { value: isRevealed ? apiKey : maskedKey, readOnly: true, className: "pr-28 font-mono text-sm", style: {
60
+ minWidth: '100%',
61
+ overflow: isRevealed ? 'auto' : 'hidden',
62
+ whiteSpace: 'nowrap',
63
+ } }) }), _jsxs("div", { className: "absolute right-1 flex gap-1", children: [_jsx(Tooltip, { content: isRevealed ? 'Hide' : 'Reveal', children: _jsx(Button, { size: "xs", color: "gray", onClick: handleReveal, className: "h-7 w-7 p-0", children: isRevealed ? (_jsx(HiEyeOff, { className: "h-4 w-4" })) : (_jsx(HiEye, { className: "h-4 w-4" })) }) }), _jsx(Tooltip, { content: copyStatus === 'copied' ? 'Copied!' : 'Copy', children: _jsx(Button, { size: "xs", color: copyStatus === 'copied' ? 'success' : 'gray', onClick: handleCopy, className: "h-7 w-7 p-0", children: copyStatus === 'copied' ? (_jsx(HiCheckCircle, { className: "h-4 w-4" })) : (_jsx(HiClipboardCopy, { className: "h-4 w-4" })) }) }), _jsx(Tooltip, { content: "Download", children: _jsx(Button, { size: "xs", color: "gray", onClick: handleDownload, className: "h-7 w-7 p-0", children: _jsx(HiDownload, { className: "h-4 w-4" }) }) })] })] }), isRevealed && (_jsx("p", { className: "mt-1 text-xs text-yellow-600 dark:text-yellow-400", children: "Key will be hidden automatically in 5 seconds" }))] }));
64
+ };
@@ -0,0 +1,5 @@
1
+ export { ApiKeyDisplay } from './ApiKeyDisplay';
2
+ export { ApiKeysCard } from './ApiKeysCard';
3
+ export { ApiKeyTable } from './ApiKeyTable';
4
+ export { CreateApiKeyModal } from './CreateApiKeyModal';
5
+ export { SecureApiKeyField } from './SecureApiKeyField';
@@ -0,0 +1,5 @@
1
+ export { ApiKeyDisplay } from './ApiKeyDisplay';
2
+ export { ApiKeysCard } from './ApiKeysCard';
3
+ export { ApiKeyTable } from './ApiKeyTable';
4
+ export { CreateApiKeyModal } from './CreateApiKeyModal';
5
+ export { SecureApiKeyField } from './SecureApiKeyField';
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import type { AgentType } from './types';
3
+ interface ChatHeaderProps {
4
+ agentType: AgentType;
5
+ setAgentType: React.Dispatch<React.SetStateAction<AgentType>>;
6
+ loading: boolean;
7
+ title?: string;
8
+ activeTasks?: number;
9
+ agentDescription?: string;
10
+ }
11
+ export declare const ChatHeader: React.FC<ChatHeaderProps>;
12
+ export {};
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { FaRobot } from 'react-icons/fa';
3
+ export const ChatHeader = ({ agentType, setAgentType, loading, title = 'AI Chat', activeTasks = 0, agentDescription = 'Financial Analysis Agent', }) => {
4
+ return (_jsxs("div", { className: "flex items-center justify-between border-b border-gray-200 p-4 dark:border-gray-700", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(FaRobot, { className: "text-secondary-500 dark:text-secondary-400 h-5 w-5" }), _jsx("h5", { className: "font-heading text-lg font-medium text-gray-900 dark:text-gray-100", children: title })] }), _jsx("div", { className: "flex items-center gap-2", children: _jsx("div", { className: "flex items-center gap-1", children: _jsx("span", { className: "text-xs text-gray-500 dark:text-gray-400", children: agentDescription }) }) })] }));
5
+ };
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ interface ChatInputAreaProps {
3
+ input: string;
4
+ loading: boolean;
5
+ dots: string;
6
+ forceDeepResearch: boolean;
7
+ textareaRef: React.RefObject<HTMLTextAreaElement>;
8
+ placeholder?: string;
9
+ deepResearchTooltip?: string;
10
+ onInputChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void;
11
+ onKeyDown: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;
12
+ onSendMessage: () => void;
13
+ onToggleDeepResearch: (enabled: boolean) => void;
14
+ }
15
+ export declare const ChatInputArea: React.FC<ChatInputAreaProps>;
16
+ export {};
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, Textarea } from 'flowbite-react';
3
+ import { IoSend } from 'react-icons/io5';
4
+ import { DeepResearchToggle } from './DeepResearchToggle';
5
+ export const ChatInputArea = ({ input, loading, dots, forceDeepResearch, textareaRef, placeholder = 'Type your message...', deepResearchTooltip, onInputChange, onKeyDown, onSendMessage, onToggleDeepResearch, }) => {
6
+ return (_jsx("div", { className: "border-t border-gray-200 p-4 dark:border-gray-700", children: _jsxs("div", { className: "flex items-end gap-2", children: [_jsxs("div", { className: "relative flex-1", children: [_jsx(DeepResearchToggle, { isEnabled: forceDeepResearch, onToggle: onToggleDeepResearch, tooltipContent: deepResearchTooltip }), _jsx(Textarea, { ref: textareaRef, className: "focus:border-secondary-500 focus:ring-secondary-500 min-h-[52px] w-full resize-none rounded-lg border-gray-200 bg-white pl-10 text-gray-900 placeholder:text-gray-500 dark:border-gray-700 dark:bg-zinc-800 dark:text-gray-100 dark:placeholder:text-gray-400", value: loading
7
+ ? `${forceDeepResearch ? 'Deep research' : 'Thinking'}${dots}`
8
+ : input, onChange: onInputChange, onKeyDown: onKeyDown, disabled: loading, placeholder: placeholder, rows: 2 })] }), _jsx(Button, { size: "sm", color: "secondary", className: "h-10 w-10 p-0", onClick: onSendMessage, disabled: loading, "aria-label": "Send", children: _jsx(IoSend, { className: "h-5 w-5" }) })] }) }));
9
+ };
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import type { Message } from './types';
3
+ interface ChatMessageProps {
4
+ message: Message;
5
+ }
6
+ export declare const ChatMessage: React.FC<ChatMessageProps>;
7
+ export {};
@@ -0,0 +1,24 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import { Card, Progress } from 'flowbite-react';
14
+ import { FaClock, FaSpinner } from 'react-icons/fa';
15
+ import ReactMarkdown from 'react-markdown';
16
+ export const ChatMessage = ({ message }) => (_jsx("div", { className: `flex ${message.user === 'You' ? 'justify-end' : 'justify-start'}`, children: _jsxs(Card, { className: `max-w-[80%] ${message.user === 'You'
17
+ ? 'bg-secondary-500 dark:bg-secondary-600 text-white'
18
+ : 'bg-gray-50 text-gray-900 dark:bg-zinc-700 dark:text-gray-100'}`, children: [_jsxs("div", { className: "mb-0.5 flex items-center justify-between text-sm font-semibold opacity-75", children: [_jsx("span", { children: message.user }), message.isPartial && (_jsxs("div", { className: "flex items-center gap-1", children: [_jsx(FaSpinner, { className: "h-3 w-3 animate-spin" }), _jsx("span", { className: "text-xs", children: "Analyzing..." })] })), message.taskId && !message.isPartial && (_jsxs("div", { className: "flex items-center gap-1", children: [_jsx(FaClock, { className: "h-3 w-3" }), _jsx("span", { className: "text-xs", children: "Deep research" })] }))] }), _jsx(ReactMarkdown, { components: {
19
+ code: (_a) => {
20
+ var { className, children } = _a, props = __rest(_a, ["className", "children"]);
21
+ const match = /language-(\w+)/.exec(className || '');
22
+ return match ? (_jsx("pre", Object.assign({ className: className }, props, { children: children }))) : (_jsx("code", Object.assign({ className: className }, props, { children: children })));
23
+ },
24
+ }, children: message.text }), message.isPartial && typeof message.progress === 'number' && (_jsxs("div", { className: "mt-3", children: [_jsxs("div", { className: "mb-1 flex items-center justify-between text-xs", children: [_jsx("span", { children: message.currentStep || 'Processing...' }), _jsxs("span", { children: [message.progress, "%"] })] }), _jsx(Progress, { progress: message.progress, size: "sm", color: "secondary", className: "w-full", "aria-label": `Task progress: ${message.progress}%` })] }))] }) }));
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ interface DeepResearchToggleProps {
3
+ isEnabled: boolean;
4
+ onToggle: (enabled: boolean) => void;
5
+ tooltipContent?: string;
6
+ }
7
+ export declare const DeepResearchToggle: React.FC<DeepResearchToggleProps>;
8
+ export {};
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Tooltip } from 'flowbite-react';
3
+ import { FaLightbulb } from 'react-icons/fa';
4
+ export const DeepResearchToggle = ({ isEnabled, onToggle, tooltipContent = 'Deep Research: Enables comprehensive analysis with up to 12 tool calls', }) => {
5
+ return (_jsx("div", { className: "absolute top-3 left-3 z-10", children: _jsx(Tooltip, { content: tooltipContent, placement: "top", children: _jsx("div", { className: `cursor-pointer transition-all duration-200 ${isEnabled
6
+ ? 'text-yellow-500 hover:text-yellow-400'
7
+ : 'text-gray-400 hover:text-yellow-400 dark:text-gray-500 dark:hover:text-yellow-400'}`, onClick: () => onToggle(!isEnabled), role: "button", "aria-label": "Toggle Deep Research Mode", tabIndex: 0, onKeyDown: (e) => {
8
+ if (e.key === 'Enter' || e.key === ' ') {
9
+ e.preventDefault();
10
+ onToggle(!isEnabled);
11
+ }
12
+ }, children: _jsx(FaLightbulb, { className: "h-4 w-4" }) }) }) }));
13
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Shared chat UI components for RoboLedger and RoboInvestor
3
+ */
4
+ export { ChatHeader } from './ChatHeader';
5
+ export { ChatInputArea } from './ChatInputArea';
6
+ export { ChatMessage } from './ChatMessage';
7
+ export { DeepResearchToggle } from './DeepResearchToggle';
8
+ export { ErrorType, categorizeError, generateMessageId, getErrorMessage, } from './types';
9
+ export type { AgentType, Message } from './types';
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Shared chat UI components for RoboLedger and RoboInvestor
3
+ */
4
+ export { ChatHeader } from './ChatHeader';
5
+ export { ChatInputArea } from './ChatInputArea';
6
+ export { ChatMessage } from './ChatMessage';
7
+ export { DeepResearchToggle } from './DeepResearchToggle';
8
+ export { ErrorType, categorizeError, generateMessageId, getErrorMessage, } from './types';
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Shared chat interface types and utilities
3
+ */
4
+ export declare const generateMessageId: () => string;
5
+ export declare enum ErrorType {
6
+ AUTHENTICATION = "AUTHENTICATION",
7
+ NOT_FOUND = "NOT_FOUND",
8
+ COMPANY_SELECTION = "COMPANY_SELECTION",
9
+ NETWORK = "NETWORK",
10
+ UNKNOWN = "UNKNOWN"
11
+ }
12
+ export declare const categorizeError: (error: Error) => ErrorType;
13
+ export declare const getErrorMessage: (errorType: ErrorType) => string;
14
+ export interface Message {
15
+ id: string;
16
+ text: string;
17
+ user: 'You' | 'Agent';
18
+ isPartial?: boolean;
19
+ taskId?: string;
20
+ progress?: number;
21
+ currentStep?: string;
22
+ }
23
+ export type AgentType = 'default';
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Shared chat interface types and utilities
3
+ */
4
+ // Helper function to generate unique IDs
5
+ export const generateMessageId = () => `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
6
+ // Error types for better error handling
7
+ export var ErrorType;
8
+ (function (ErrorType) {
9
+ ErrorType["AUTHENTICATION"] = "AUTHENTICATION";
10
+ ErrorType["NOT_FOUND"] = "NOT_FOUND";
11
+ ErrorType["COMPANY_SELECTION"] = "COMPANY_SELECTION";
12
+ ErrorType["NETWORK"] = "NETWORK";
13
+ ErrorType["UNKNOWN"] = "UNKNOWN";
14
+ })(ErrorType || (ErrorType = {}));
15
+ // Helper function to categorize errors
16
+ export const categorizeError = (error) => {
17
+ const message = error.message.toLowerCase();
18
+ if (message.includes('authentication') ||
19
+ message.includes('unauthorized') ||
20
+ message.includes('401')) {
21
+ return ErrorType.AUTHENTICATION;
22
+ }
23
+ if (message.includes('not found') || message.includes('404')) {
24
+ return ErrorType.NOT_FOUND;
25
+ }
26
+ if (message.includes('graph_id') || message.includes('company')) {
27
+ return ErrorType.COMPANY_SELECTION;
28
+ }
29
+ if (message.includes('network') ||
30
+ message.includes('fetch') ||
31
+ message.includes('timeout')) {
32
+ return ErrorType.NETWORK;
33
+ }
34
+ return ErrorType.UNKNOWN;
35
+ };
36
+ // Get user-friendly error message based on error type
37
+ export const getErrorMessage = (errorType) => {
38
+ switch (errorType) {
39
+ case ErrorType.AUTHENTICATION:
40
+ return 'Please log in to access your financial data.';
41
+ case ErrorType.NOT_FOUND:
42
+ return 'The requested data was not found. Please verify your company selection.';
43
+ case ErrorType.COMPANY_SELECTION:
44
+ return 'Please select a company first to access your financial data.';
45
+ case ErrorType.NETWORK:
46
+ return 'Network error occurred. Please check your connection and try again.';
47
+ case ErrorType.UNKNOWN:
48
+ default:
49
+ return 'Sorry, there was an error processing your request. Please try again.';
50
+ }
51
+ };
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ export interface PasswordRequirement {
3
+ text: string;
4
+ isValid?: boolean;
5
+ }
6
+ export interface PasswordRequirementsProps {
7
+ requirements?: PasswordRequirement[];
8
+ className?: string;
9
+ }
10
+ export declare const PasswordRequirements: React.FC<PasswordRequirementsProps>;
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ const defaultRequirements = [
3
+ { text: 'At least 12 characters (and up to 128 characters)' },
4
+ { text: 'At least one uppercase letter' },
5
+ { text: 'At least one lowercase letter' },
6
+ { text: 'At least one digit' },
7
+ { text: 'At least one special character, e.g., ! @ # $ % ^ & *' },
8
+ ];
9
+ export const PasswordRequirements = ({ requirements = defaultRequirements, className = '', }) => {
10
+ return (_jsxs("div", { className: `col-span-full mb-3 ${className}`, children: [_jsx("div", { className: "mt-3 mb-1 text-sm font-medium dark:text-white", children: "Password requirements:" }), _jsx("div", { className: "mb-1 text-sm font-normal text-gray-500 dark:text-gray-400", children: "Ensure that these requirements are met:" }), _jsx("ul", { className: "space-y-1 pl-4 text-gray-500 dark:text-gray-400", children: requirements.map((req, index) => (_jsxs("li", { className: `text-xs font-normal ${req.isValid !== undefined
11
+ ? req.isValid
12
+ ? 'text-green-600 dark:text-green-400'
13
+ : 'text-red-600 dark:text-red-400'
14
+ : ''}`, children: [req.isValid !== undefined && (_jsx("span", { className: "mr-1", children: req.isValid ? '✓' : '✗' })), req.text] }, index))) })] }));
15
+ };
@@ -0,0 +1,11 @@
1
+ import type { ComponentProps, FC } from 'react';
2
+ import React from 'react';
3
+ export interface SettingsCardProps {
4
+ title: string;
5
+ description?: string;
6
+ icon?: FC<ComponentProps<'svg'>>;
7
+ children: React.ReactNode;
8
+ theme?: any;
9
+ className?: string;
10
+ }
11
+ export declare const SettingsCard: React.FC<SettingsCardProps>;
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Card } from 'flowbite-react';
3
+ export const SettingsCard = ({ title, description, icon: Icon, children, theme, className = '', }) => {
4
+ return (_jsxs(Card, { theme: theme, className: className, children: [_jsxs("div", { className: "mb-6", children: [Icon && (_jsxs("div", { className: "mb-4 flex items-start gap-3", children: [_jsx("div", { className: "rounded-lg bg-zinc-100 p-2 dark:bg-zinc-800", children: _jsx(Icon, { className: "h-5 w-5 text-zinc-600 dark:text-zinc-400" }) }), _jsxs("div", { className: "flex-1", children: [_jsx("h3", { className: "font-heading text-lg font-semibold text-zinc-900 dark:text-zinc-100", children: title }), description && (_jsx("p", { className: "mt-1 text-sm text-zinc-600 dark:text-zinc-400", children: description }))] })] })), !Icon && (_jsxs(_Fragment, { children: [_jsx("h3", { className: "font-heading text-lg font-semibold text-zinc-900 dark:text-zinc-100", children: title }), description && (_jsx("p", { className: "mt-1 text-sm text-zinc-600 dark:text-zinc-400", children: description }))] }))] }), children] }));
5
+ };
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+ export interface SettingsFormFieldProps {
3
+ id: string;
4
+ label: string;
5
+ name?: string;
6
+ type?: 'text' | 'email' | 'password' | 'number';
7
+ placeholder?: string;
8
+ defaultValue?: string;
9
+ value?: string;
10
+ required?: boolean;
11
+ disabled?: boolean;
12
+ theme?: any;
13
+ className?: string;
14
+ onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
15
+ min?: string | number;
16
+ max?: string | number;
17
+ }
18
+ export declare const SettingsFormField: React.FC<SettingsFormFieldProps>;
@@ -0,0 +1,17 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
+ import { Label, TextInput } from 'flowbite-react';
14
+ export const SettingsFormField = (_a) => {
15
+ var { id, label, name = id, type = 'text', placeholder, defaultValue, value, required = false, disabled = false, theme, className = '', onChange, min, max } = _a, props = __rest(_a, ["id", "label", "name", "type", "placeholder", "defaultValue", "value", "required", "disabled", "theme", "className", "onChange", "min", "max"]);
16
+ return (_jsxs("div", { className: `grid grid-cols-1 gap-y-3 ${className}`, children: [_jsx(Label, { theme: theme === null || theme === void 0 ? void 0 : theme.label, htmlFor: id, children: label }), _jsx(TextInput, Object.assign({ theme: theme === null || theme === void 0 ? void 0 : theme.textInput, id: id, name: name, type: type, placeholder: placeholder, defaultValue: defaultValue, value: value, required: required, disabled: disabled, onChange: onChange, min: min, max: max }, props))] }));
17
+ };
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ export interface StatusAlertProps {
3
+ type: 'success' | 'error';
4
+ message: string;
5
+ theme?: any;
6
+ className?: string;
7
+ }
8
+ export declare const StatusAlert: React.FC<StatusAlertProps>;
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Alert } from 'flowbite-react';
3
+ import { HiCheckCircle, HiExclamationCircle } from 'react-icons/hi';
4
+ export const StatusAlert = ({ type, message, theme, className = 'mb-4', }) => {
5
+ const isSuccess = type === 'success';
6
+ return (_jsx(Alert, { theme: theme, color: isSuccess ? 'success' : 'failure', className: `${className} relative z-10 w-full`, children: _jsxs("div", { className: "flex items-center", children: [isSuccess ? (_jsx(HiCheckCircle, { className: "mr-2 h-4 w-4 shrink-0" })) : (_jsx(HiExclamationCircle, { className: "mr-2 h-4 w-4 shrink-0" })), _jsx("span", { className: "font-medium", children: isSuccess ? 'Success!' : 'Error!' }), _jsx("span", { className: "ml-1", children: message })] }) }));
7
+ };
@@ -0,0 +1,4 @@
1
+ export { PasswordRequirements } from './PasswordRequirements';
2
+ export { SettingsCard } from './SettingsCard';
3
+ export { SettingsFormField } from './SettingsFormField';
4
+ export { StatusAlert } from './StatusAlert';
@@ -0,0 +1,4 @@
1
+ export { PasswordRequirements } from './PasswordRequirements';
2
+ export { SettingsCard } from './SettingsCard';
3
+ export { SettingsFormField } from './SettingsFormField';
4
+ export { StatusAlert } from './StatusAlert';
@@ -0,0 +1,13 @@
1
+ export * from './api-keys';
2
+ export * from './forms';
3
+ export * from './layout';
4
+ export * from './settings';
5
+ export { ConfirmModal } from './ConfirmModal';
6
+ export { EmptyState } from './EmptyState';
7
+ export { LoadingState } from './LoadingState';
8
+ export { AnimatedLogo, LogoBadge } from './Logo';
9
+ export { BrandSpinner, Spinner } from './Spinner';
10
+ export { StatCard } from './StatCard';
11
+ export * from './chat';
12
+ export * from './support';
13
+ export * from './types';
@@ -0,0 +1,18 @@
1
+ // Settings Components
2
+ export * from './api-keys';
3
+ export * from './forms';
4
+ export * from './layout';
5
+ export * from './settings';
6
+ // UI Components
7
+ export { ConfirmModal } from './ConfirmModal';
8
+ export { EmptyState } from './EmptyState';
9
+ export { LoadingState } from './LoadingState';
10
+ export { AnimatedLogo, LogoBadge } from './Logo';
11
+ export { BrandSpinner, Spinner } from './Spinner';
12
+ export { StatCard } from './StatCard';
13
+ // Chat Components
14
+ export * from './chat';
15
+ // Support Components
16
+ export * from './support';
17
+ // Types
18
+ export * from './types';
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ export interface CoreNavbarProps {
3
+ appName: string;
4
+ currentApp: 'roboledger' | 'roboinvestor' | 'robosystems';
5
+ apiUrl?: string;
6
+ homeHref?: string;
7
+ logoAltText?: string;
8
+ additionalComponents?: React.ReactNode;
9
+ className?: string;
10
+ borderColorClass?: string;
11
+ useCustomThemeToggle?: boolean;
12
+ showAppSwitcherFirst?: boolean;
13
+ }
14
+ export declare function CoreNavbar({ appName, currentApp, apiUrl, homeHref, logoAltText, additionalComponents, className, borderColorClass, useCustomThemeToggle, showAppSwitcherFirst, }: CoreNavbarProps): React.JSX.Element;
@@ -0,0 +1,53 @@
1
+ 'use client';
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { DarkThemeToggle, Dropdown, DropdownDivider, DropdownHeader, DropdownItem, Navbar as FlowbiteNavbar, NavbarBrand, Tooltip, } from 'flowbite-react';
4
+ import Link from 'next/link';
5
+ import { HiMenuAlt1, HiUserCircle, HiX } from 'react-icons/hi';
6
+ import { AppSwitcher } from '../../auth-components';
7
+ import { useAuth } from '../../auth-components/AuthProvider';
8
+ import { useSidebarContext } from '../../contexts';
9
+ import { useMediaQuery, useUser } from '../../hooks';
10
+ import { customTheme } from '../../theme';
11
+ import { LogoBadge } from '../Logo';
12
+ import { ThemeToggle } from './ThemeToggle';
13
+ export function CoreNavbar({ appName, currentApp, apiUrl = process.env.NEXT_PUBLIC_ROBOSYSTEMS_API_URL ||
14
+ 'http://localhost:8000', homeHref = '/home', logoAltText, additionalComponents, className = '', borderColorClass = 'dark:border-gray-700', useCustomThemeToggle = true, showAppSwitcherFirst = false, }) {
15
+ const sidebar = useSidebarContext();
16
+ const isDesktop = useMediaQuery('(min-width: 1024px)');
17
+ const { user } = useUser();
18
+ const { logout } = useAuth();
19
+ const altText = logoAltText || `${appName} Logo`;
20
+ function handleToggleSidebar() {
21
+ if (isDesktop) {
22
+ sidebar.desktop.toggle();
23
+ }
24
+ else {
25
+ sidebar.mobile.toggle();
26
+ }
27
+ }
28
+ const handleLogout = async () => {
29
+ try {
30
+ // logout() clears the backend session and hard-redirects to /login.
31
+ await logout();
32
+ }
33
+ catch (error) {
34
+ console.error('Logout failed:', error);
35
+ // Fallback: if logout() threw before it could redirect, still get the
36
+ // user out of the authenticated area to the public homepage.
37
+ window.location.href = '/';
38
+ }
39
+ };
40
+ const renderThemeToggle = () => {
41
+ if (useCustomThemeToggle) {
42
+ return _jsx(ThemeToggle, {});
43
+ }
44
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: "hidden dark:block", children: _jsx(Tooltip, { content: "Toggle light mode", theme: customTheme.tooltip, children: _jsx(DarkThemeToggle, {}) }) }), _jsx("div", { className: "dark:hidden", children: _jsx(Tooltip, { content: "Toggle dark mode", theme: customTheme.tooltip, children: _jsx(DarkThemeToggle, {}) }) })] }));
45
+ };
46
+ const renderAppSwitcher = () => (_jsx(Tooltip, { content: "Switch apps", theme: customTheme.tooltip, children: _jsx(AppSwitcher, { apiUrl: apiUrl, currentApp: currentApp }) }));
47
+ return (_jsx(FlowbiteNavbar, { fluid: true, theme: customTheme.navbar, className: `fixed top-0 z-30 w-full border-b border-gray-200 p-0 ${borderColorClass} bg-white sm:p-0 dark:bg-black ${className}`, children: _jsx("div", { className: "w-full p-3 pr-4", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center", children: [_jsxs("button", { onClick: handleToggleSidebar, className: "mr-3 cursor-pointer rounded-sm p-2 text-gray-600 hover:bg-zinc-100 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-zinc-700 dark:hover:text-white", children: [_jsx("span", { className: "sr-only", children: "Toggle sidebar" }), _jsx("div", { className: "lg:hidden", children: sidebar.mobile.isOpen ? (_jsx(HiX, { className: "h-6 w-6" })) : (_jsx(HiMenuAlt1, { className: "h-6 w-6" })) }), _jsx("div", { className: "hidden lg:block", children: _jsx(HiMenuAlt1, { className: "h-6 w-6" }) })] }), _jsxs(NavbarBrand, { as: Link, href: homeHref, className: "mr-14", children: [_jsx(LogoBadge, { app: currentApp, animate: "once", className: "mr-2 h-10 w-10" }), _jsx("span", { className: "font-heading mt-2 ml-1 self-center text-2xl font-semibold whitespace-nowrap text-gray-900 dark:text-white", children: appName })] })] }), _jsx("div", { className: "flex items-center lg:gap-3", children: _jsxs("div", { className: "flex items-center", children: [additionalComponents && (_jsx("div", { className: "mr-2 hidden md:block", children: additionalComponents })), _jsxs("div", { className: "flex items-center space-x-2", children: [showAppSwitcherFirst && renderAppSwitcher(), renderThemeToggle(), !showAppSwitcherFirst && renderAppSwitcher(), _jsx(UserDropdown, { user: user, onLogout: handleLogout })] })] }) })] }) }) }));
48
+ }
49
+ function UserDropdown({ user, onLogout }) {
50
+ return (_jsx("div", { className: "relative", children: _jsxs(Dropdown, { theme: Object.assign(Object.assign({}, customTheme.dropdown), { floating: Object.assign(Object.assign({}, customTheme.dropdown.floating), { base: `${customTheme.dropdown.floating.base} z-50! w-64` }) }), arrowIcon: false, inline: true, label: _jsxs("span", { className: "inline-flex h-10 w-10 items-center justify-center rounded-lg text-sm text-gray-500 hover:bg-zinc-100 focus:ring-2 focus:ring-gray-200 focus:outline-hidden dark:text-gray-400 dark:hover:bg-zinc-700 dark:focus:ring-gray-600", children: [_jsx("span", { className: "sr-only", children: "User menu" }), _jsx(HiUserCircle, { className: "h-6 w-6" })] }), children: [_jsxs(DropdownHeader, { theme: { header: customTheme.dropdown.floating.header }, className: "px-4 py-3", children: [_jsx("div", { className: "block text-sm font-medium text-gray-900 dark:text-white", children: (user === null || user === void 0 ? void 0 : user.name) || 'User' }), (user === null || user === void 0 ? void 0 : user.email) && (_jsx("div", { className: "block truncate text-sm text-gray-500 dark:text-gray-400", children: user.email }))] }), _jsx(DropdownItem, { theme: customTheme.dropdown.floating.item, as: Link, href: "/settings", className: "flex w-full items-center space-x-3 p-3", children: "User Settings" }), _jsx(DropdownDivider, { theme: { divider: customTheme.dropdown.floating.divider } }), _jsx(DropdownItem, { theme: customTheme.dropdown.floating.item, onClick: () => {
51
+ onLogout();
52
+ }, className: "flex w-full items-center space-x-3 p-3", children: "Sign out" })] }) }));
53
+ }
@@ -0,0 +1,28 @@
1
+ import type { ComponentProps, FC, HTMLAttributeAnchorTarget } from 'react';
2
+ import React from 'react';
3
+ export interface SidebarItemData {
4
+ href?: string;
5
+ target?: HTMLAttributeAnchorTarget;
6
+ icon?: FC<ComponentProps<'svg'>>;
7
+ label: string;
8
+ items?: SidebarItemData[];
9
+ badge?: string;
10
+ }
11
+ export interface CoreSidebarProps {
12
+ navigationItems: SidebarItemData[];
13
+ features?: {
14
+ aiChat?: boolean;
15
+ companyDropdown?: boolean;
16
+ showOrgSection?: boolean;
17
+ };
18
+ bottomMenuActions?: {
19
+ label: string;
20
+ icon: FC<ComponentProps<'svg'>>;
21
+ onClick: () => void;
22
+ tooltip: string;
23
+ }[];
24
+ additionalMobileComponents?: React.ReactNode;
25
+ className?: string;
26
+ borderColorClass?: string;
27
+ }
28
+ export declare function CoreSidebar({ navigationItems, features, bottomMenuActions, additionalMobileComponents, className, borderColorClass, }: CoreSidebarProps): React.JSX.Element;