@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,62 @@
1
+ 'use client';
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { Button, Sidebar, SidebarCollapse, SidebarItem, SidebarItemGroup, SidebarItems, Tooltip, } from 'flowbite-react';
4
+ import Link from 'next/link';
5
+ import { usePathname } from 'next/navigation';
6
+ import { HiCog, HiOfficeBuilding } from 'react-icons/hi';
7
+ import { twMerge } from 'tailwind-merge';
8
+ import { useOrg, useSidebarContext } from '../../contexts';
9
+ import { customTheme } from '../../theme';
10
+ export function CoreSidebar({ navigationItems, features = {}, bottomMenuActions = [], additionalMobileComponents, className = '', borderColorClass = 'dark:border-gray-700', }) {
11
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: "lg:hidden", children: _jsx(MobileSidebar, { navigationItems: navigationItems, features: features, bottomMenuActions: bottomMenuActions, additionalMobileComponents: additionalMobileComponents, borderColorClass: borderColorClass }) }), _jsx("div", { className: `hidden lg:block ${className}`, children: _jsx(DesktopSidebar, { navigationItems: navigationItems, features: features, bottomMenuActions: bottomMenuActions, borderColorClass: borderColorClass }) })] }));
12
+ }
13
+ function DesktopSidebar({ navigationItems, features, bottomMenuActions, borderColorClass, }) {
14
+ const pathname = usePathname();
15
+ const { isCollapsed } = useSidebarContext().desktop;
16
+ return (_jsx(Sidebar, { "aria-label": "Sidebar with multi-level dropdown example", theme: customTheme.sidebar, collapsed: isCollapsed, className: twMerge(`fixed inset-y-0 left-0 z-20 flex h-full shrink-0 flex-col border-r border-gray-200 pt-16 duration-75 ${borderColorClass} lg:flex`), id: "sidebar", children: _jsxs("div", { className: "flex h-full flex-col justify-between", children: [_jsx("div", { className: "py-2", children: _jsxs(SidebarItems, { children: [_jsx(OrgSection, { isCollapsed: isCollapsed, showOrgSection: features.showOrgSection }), _jsx(SidebarItemGroup, { className: "mt-0 border-t-0 pt-2 pb-1", children: navigationItems.map((item) => (_jsx(CustomSidebarItem, Object.assign({}, item, { pathname: pathname }), item.label))) })] }) }), _jsx(BottomMenu, { isCollapsed: isCollapsed, features: features, bottomMenuActions: bottomMenuActions })] }) }));
17
+ }
18
+ function MobileSidebar({ navigationItems, features, bottomMenuActions, additionalMobileComponents, borderColorClass, }) {
19
+ const pathname = usePathname();
20
+ const { isOpen, close } = useSidebarContext().mobile;
21
+ if (!isOpen)
22
+ return null;
23
+ return (_jsxs(_Fragment, { children: [_jsx(Sidebar, { "aria-label": "Sidebar with multi-level dropdown example", theme: customTheme.sidebar, className: twMerge(`fixed inset-y-0 left-0 z-20 hidden h-full shrink-0 flex-col border-r border-gray-200 pt-16 ${borderColorClass} lg:flex`, isOpen && 'flex'), id: "sidebar", children: _jsxs("div", { className: "flex h-full flex-col justify-between", children: [_jsxs("div", { className: "py-2", children: [additionalMobileComponents && (_jsx("div", { className: "hidden pb-2 max-md:block", children: additionalMobileComponents })), _jsxs(SidebarItems, { children: [_jsx(OrgSection, { isCollapsed: false, showOrgSection: features.showOrgSection }), _jsx(SidebarItemGroup, { className: "mt-0 border-t-0 pt-2 pb-1", children: navigationItems.map((item) => (_jsx(CustomSidebarItem, Object.assign({}, item, { pathname: pathname }), item.label))) })] })] }), _jsx(BottomMenu, { isCollapsed: false, features: features, bottomMenuActions: bottomMenuActions })] }) }), _jsx("div", { onClick: close, "aria-hidden": "true", className: "fixed inset-0 z-10 h-full w-full bg-zinc-900/50 pt-16 dark:bg-zinc-900/90" })] }));
24
+ }
25
+ function CustomSidebarItem({ href, target, icon: Icon, label, items, badge, pathname, }) {
26
+ if (!(items === null || items === void 0 ? void 0 : items.length)) {
27
+ const isExternal = target === '_blank' || (href === null || href === void 0 ? void 0 : href.startsWith('http'));
28
+ if (isExternal) {
29
+ return (_jsx(SidebarItem, { href: href || '#', icon: Icon, active: pathname === href, theme: customTheme.sidebar.item, className: pathname === href
30
+ ? 'bg-primary-50 text-primary-700 dark:bg-primary-200 dark:text-primary-800'
31
+ : '', children: label }));
32
+ }
33
+ return (_jsx(SidebarItem, { as: Link, href: href || '#', icon: Icon, active: pathname === href, theme: customTheme.sidebar.item, className: pathname === href
34
+ ? 'bg-zinc-100 text-gray-900 dark:bg-zinc-800 dark:text-gray-200'
35
+ : '', children: label }));
36
+ }
37
+ return (_jsx(SidebarCollapse, { icon: Icon, label: label, theme: customTheme.sidebar.collapse, open: items.some((item) => pathname === item.href), children: items.map((item) => {
38
+ var _a;
39
+ const isExternal = item.target === '_blank' || ((_a = item.href) === null || _a === void 0 ? void 0 : _a.startsWith('http'));
40
+ if (isExternal) {
41
+ return (_jsx(SidebarItem, { href: item.href || '#', active: pathname === item.href, theme: customTheme.sidebar.item, className: pathname === item.href
42
+ ? 'bg-primary-50 text-primary-700 dark:bg-primary-200 dark:text-primary-800'
43
+ : '', children: item.label }, item.label));
44
+ }
45
+ return (_jsx(SidebarItem, { as: Link, href: item.href || '#', active: pathname === item.href, theme: customTheme.sidebar.item, className: pathname === item.href
46
+ ? 'bg-primary-50 text-primary-700 dark:bg-primary-200 dark:text-primary-800'
47
+ : '', children: item.label }, item.label));
48
+ }) }));
49
+ }
50
+ function OrgSection({ isCollapsed, showOrgSection = true, }) {
51
+ const { currentOrg } = useOrg();
52
+ const pathname = usePathname();
53
+ const isActive = pathname === '/organization';
54
+ if (!showOrgSection || !currentOrg)
55
+ return null;
56
+ return (_jsx(SidebarItemGroup, { className: "border-b border-gray-200 pb-2 dark:border-gray-700", children: _jsx(SidebarItem, { as: Link, href: "/organization", icon: HiOfficeBuilding, active: isActive, theme: customTheme.sidebar.item, className: isActive
57
+ ? 'bg-zinc-100 text-gray-900 dark:bg-zinc-800 dark:text-gray-200'
58
+ : '', children: _jsx("span", { className: "truncate text-sm", children: currentOrg.name }) }) }));
59
+ }
60
+ function BottomMenu({ isCollapsed, features, bottomMenuActions, }) {
61
+ return (_jsxs("div", { className: `flex items-center justify-center border-t border-gray-200 px-4 py-4 dark:border-gray-700 ${isCollapsed ? 'flex-col gap-y-2' : 'gap-x-5'}`, children: [_jsx(Tooltip, { content: "Settings", theme: customTheme.tooltip, children: _jsx(Button, { as: Link, href: "/settings", color: "ghost", className: "rounded-lg p-2 hover:bg-gray-100 dark:hover:bg-gray-700", children: _jsx(HiCog, { className: "text-lg text-gray-500 dark:text-gray-400" }) }) }), bottomMenuActions.map((action, index) => (_jsx(Tooltip, { content: action.tooltip, theme: customTheme.tooltip, children: _jsx(Button, { onClick: action.onClick, color: "ghost", className: "rounded-lg p-2 hover:bg-gray-100 dark:hover:bg-gray-700", children: _jsx(action.icon, { className: "text-lg text-gray-500 dark:text-gray-400" }) }) }, index)))] }));
62
+ }
@@ -0,0 +1,28 @@
1
+ import { type ComponentType } from 'react';
2
+ export interface FooterLink {
3
+ label: string;
4
+ href: string;
5
+ }
6
+ export interface LandingFooterProps {
7
+ /** Marketing blurb shown under the wordmark — app-specific. */
8
+ tagline: string;
9
+ /** Links for the "Product" column — app-specific routes/anchors. */
10
+ productLinks: FooterLink[];
11
+ /**
12
+ * The app's own ContactModal. When provided, a "Contact" entry appears in the
13
+ * Company column and opens this modal; omit it to hide Contact. Kept per-app
14
+ * (rather than shared) so each product keeps its own contact copy.
15
+ */
16
+ contactModal?: ComponentType<{
17
+ isOpen: boolean;
18
+ onClose: () => void;
19
+ }>;
20
+ }
21
+ /**
22
+ * The shared marketing-site footer for all three apps. The brand column, social
23
+ * row, the Applications cross-links, the Company column and copyright are
24
+ * derived from CURRENT_APP + APP_CONFIGS so each app reskins automatically;
25
+ * only the tagline and Product links vary and are passed in. Contact stays
26
+ * per-app via the `contactModal` prop.
27
+ */
28
+ export declare function LandingFooter({ tagline, productLinks, contactModal: ContactModal, }: LandingFooterProps): import("react").JSX.Element;
@@ -0,0 +1,34 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import Image from 'next/image';
4
+ import Link from 'next/link';
5
+ import { useState } from 'react';
6
+ import { CURRENT_APP, getAppConfig } from '../../auth-core/config';
7
+ /** Fixed cross-app ordering for the Applications column. */
8
+ const APP_ORDER = ['robosystems', 'roboledger', 'roboinvestor'];
9
+ const linkClass = 'text-gray-400 transition-colors hover:text-white';
10
+ const headingClass = 'mb-4 text-sm font-semibold tracking-wider text-gray-400 uppercase';
11
+ /**
12
+ * The shared marketing-site footer for all three apps. The brand column, social
13
+ * row, the Applications cross-links, the Company column and copyright are
14
+ * derived from CURRENT_APP + APP_CONFIGS so each app reskins automatically;
15
+ * only the tagline and Product links vary and are passed in. Contact stays
16
+ * per-app via the `contactModal` prop.
17
+ */
18
+ export function LandingFooter({ tagline, productLinks, contactModal: ContactModal, }) {
19
+ const [showContact, setShowContact] = useState(false);
20
+ const current = getAppConfig(CURRENT_APP);
21
+ const isRoboSystems = CURRENT_APP === 'robosystems';
22
+ // RoboSystems serves Blog/Privacy/Terms itself; the other apps link out to it.
23
+ const companyBase = isRoboSystems ? '' : getAppConfig('robosystems').url;
24
+ const companyLinkProps = isRoboSystems
25
+ ? {}
26
+ : { target: '_blank', rel: 'noopener noreferrer' };
27
+ return (_jsxs("footer", { className: "border-t border-gray-800 bg-zinc-950", children: [_jsxs("div", { className: "mx-auto max-w-7xl px-4 py-12 sm:px-6 lg:px-8", children: [_jsxs("div", { className: "grid gap-4 md:grid-cols-5 lg:gap-6", children: [_jsxs("div", { className: "md:col-span-2", children: [_jsxs("div", { className: "mb-4 flex items-center gap-2", children: [_jsx(Image, { src: `/images/logos/${CURRENT_APP}.png`, alt: current.displayName, width: 32, height: 32, className: "rounded-lg" }), _jsx("span", { className: "font-heading text-xl font-semibold text-white", children: current.displayName })] }), _jsx("p", { className: "mb-4 max-w-md text-sm text-gray-400", children: tagline }), _jsxs("div", { className: "flex gap-4", children: [_jsx(Link, { href: "https://github.com/RoboFinSystems", target: "_blank", rel: "noopener noreferrer", "aria-label": "RoboSystems on GitHub", className: linkClass, children: _jsx("svg", { className: "h-6 w-6", fill: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { d: "M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" }) }) }), _jsx(Link, { href: "https://x.com/robofinsystems", target: "_blank", rel: "noopener noreferrer", "aria-label": "RoboSystems on X", className: linkClass, children: _jsx("svg", { className: "h-6 w-6", fill: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { d: "M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z" }) }) }), _jsx(Link, { href: "https://www.linkedin.com/company/robofinsystems", target: "_blank", rel: "noopener noreferrer", "aria-label": "RoboSystems on LinkedIn", className: linkClass, children: _jsx("svg", { className: "h-6 w-6", fill: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { d: "M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z" }) }) }), _jsx(Link, { href: "https://www.youtube.com/@RoboSystems", target: "_blank", rel: "noopener noreferrer", "aria-label": "RoboSystems on YouTube", className: linkClass, children: _jsx("svg", { className: "h-6 w-6", fill: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { d: "M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z" }) }) })] })] }), _jsxs("div", { children: [_jsx("h3", { className: headingClass, children: "Product" }), _jsx("ul", { className: "space-y-2 text-sm", children: productLinks.map((link) => (_jsx("li", { children: _jsx(Link, { href: link.href, className: linkClass, children: link.label }) }, link.href))) })] }), _jsxs("div", { children: [_jsx("h3", { className: headingClass, children: "Applications" }), _jsx("ul", { className: "space-y-2 text-sm", children: APP_ORDER.map((app) => {
28
+ const cfg = getAppConfig(app);
29
+ const isCurrent = app === CURRENT_APP;
30
+ return (_jsx("li", { children: _jsx(Link, Object.assign({ href: cfg.url }, (isCurrent
31
+ ? {}
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, 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" })) }), 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
+ }
@@ -0,0 +1,8 @@
1
+ import type { PropsWithChildren } from 'react';
2
+ interface PageContainerProps extends PropsWithChildren {
3
+ spacing?: 'tight' | 'normal' | 'loose';
4
+ maxWidth?: 'sm' | 'md' | 'lg' | 'xl' | 'full';
5
+ className?: string;
6
+ }
7
+ export declare function PageContainer({ children, spacing, maxWidth, className, }: PageContainerProps): import("react").JSX.Element;
8
+ export {};
@@ -0,0 +1,17 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ export function PageContainer({ children, spacing = 'normal', maxWidth = 'xl', className = '', }) {
4
+ const spacingClasses = {
5
+ tight: 'gap-4',
6
+ normal: 'gap-6',
7
+ loose: 'gap-8',
8
+ };
9
+ const maxWidthClasses = {
10
+ sm: 'max-w-sm mx-auto',
11
+ md: 'max-w-md mx-auto',
12
+ lg: 'max-w-lg mx-auto',
13
+ xl: 'max-w-7xl mx-auto',
14
+ full: 'max-w-none',
15
+ };
16
+ return (_jsx("div", { className: `grid grid-cols-1 px-4 pb-1 ${spacingClasses[spacing]} ${maxWidthClasses[maxWidth]} ${className}`, children: children }));
17
+ }
@@ -0,0 +1,23 @@
1
+ import type { ComponentType, ReactNode } from 'react';
2
+ export interface PageHeaderProps {
3
+ /**
4
+ * Icon rendered in white on the brand-gradient chip — typically a
5
+ * react-icons `Hi*` component, e.g. `icon={HiHome}`.
6
+ */
7
+ icon: ComponentType<{
8
+ className?: string;
9
+ }>;
10
+ title: string;
11
+ subtitle?: ReactNode;
12
+ /** Optional right-aligned content (buttons, menus). */
13
+ actions?: ReactNode;
14
+ /** Extra classes on the outer wrapper, e.g. `mb-6`. */
15
+ className?: string;
16
+ }
17
+ /**
18
+ * The standard page header used across the authenticated app: a white icon on
19
+ * the app's brand-gradient chip, a title, an optional subtitle, and optional
20
+ * right-aligned actions. The gradient spans the brand `primary` → `secondary`
21
+ * → `accent` tokens, so it reskins to each app automatically.
22
+ */
23
+ export declare function PageHeader({ icon: Icon, title, subtitle, actions, className, }: PageHeaderProps): import("react").JSX.Element;
@@ -0,0 +1,12 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { twMerge } from 'tailwind-merge';
4
+ /**
5
+ * The standard page header used across the authenticated app: a white icon on
6
+ * the app's brand-gradient chip, a title, an optional subtitle, and optional
7
+ * right-aligned actions. The gradient spans the brand `primary` → `secondary`
8
+ * → `accent` tokens, so it reskins to each app automatically.
9
+ */
10
+ export function PageHeader({ icon: Icon, title, subtitle, actions, className, }) {
11
+ return (_jsxs("div", { className: twMerge('flex items-start justify-between gap-4', className), children: [_jsxs("div", { className: "flex items-center gap-4", children: [_jsx("div", { className: "from-primary-500 via-secondary-500 to-accent-500 shrink-0 rounded-lg bg-gradient-to-br p-3", children: _jsx(Icon, { className: "h-8 w-8 text-white" }) }), _jsxs("div", { children: [_jsx("h1", { className: "font-heading text-3xl font-bold text-gray-900 dark:text-white", children: title }), subtitle && (_jsx("div", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: subtitle }))] })] }), actions && _jsx("div", { className: "flex shrink-0 gap-2", children: actions })] }));
12
+ }
@@ -0,0 +1,10 @@
1
+ import type { PropsWithChildren } from 'react';
2
+ interface SettingsContainerProps extends PropsWithChildren {
3
+ className?: string;
4
+ }
5
+ /**
6
+ * Standardized container for settings pages
7
+ * Ensures consistent spacing and layout across all settings implementations
8
+ */
9
+ export declare function SettingsContainer({ children, className, }: SettingsContainerProps): import("react").JSX.Element;
10
+ export {};
@@ -0,0 +1,9 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ /**
4
+ * Standardized container for settings pages
5
+ * Ensures consistent spacing and layout across all settings implementations
6
+ */
7
+ export function SettingsContainer({ children, className = '', }) {
8
+ return (_jsx("div", { className: `grid grid-cols-1 gap-6 px-4 pb-1 ${className}`, children: children }));
9
+ }
@@ -0,0 +1,4 @@
1
+ export interface ThemeToggleProps {
2
+ className?: string;
3
+ }
4
+ export declare function ThemeToggle({ className }: ThemeToggleProps): import("react").JSX.Element;
@@ -0,0 +1,6 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { DarkThemeToggle, Tooltip } from 'flowbite-react';
4
+ export function ThemeToggle({ className = '' }) {
5
+ return (_jsxs("div", { className: className, children: [_jsx("div", { className: "hidden dark:block", children: _jsx(Tooltip, { content: "Toggle light mode", children: _jsx(DarkThemeToggle, {}) }) }), _jsx("div", { className: "dark:hidden", children: _jsx(Tooltip, { content: "Toggle dark mode", children: _jsx(DarkThemeToggle, {}) }) })] }));
6
+ }
@@ -0,0 +1,7 @@
1
+ export { CoreNavbar } from './CoreNavbar';
2
+ export { CoreSidebar, type SidebarItemData } from './CoreSidebar';
3
+ export { LandingFooter, type FooterLink, type LandingFooterProps, } from './LandingFooter';
4
+ export { PageContainer } from './PageContainer';
5
+ export { PageHeader, type PageHeaderProps } from './PageHeader';
6
+ export { SettingsContainer } from './SettingsContainer';
7
+ export { ThemeToggle } from './ThemeToggle';
@@ -0,0 +1,7 @@
1
+ export { CoreNavbar } from './CoreNavbar';
2
+ export { CoreSidebar } from './CoreSidebar';
3
+ export { LandingFooter, } from './LandingFooter';
4
+ export { PageContainer } from './PageContainer';
5
+ export { PageHeader } from './PageHeader';
6
+ export { SettingsContainer } from './SettingsContainer';
7
+ export { ThemeToggle } from './ThemeToggle';
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import type { AuthUser, UserUpdateData } from '../types';
3
+ export interface GeneralInformationCardProps {
4
+ user: AuthUser;
5
+ theme?: any;
6
+ onUpdate?: (data: UserUpdateData) => Promise<void>;
7
+ onRefresh?: () => Promise<void>;
8
+ onSuccess?: (message: string) => void;
9
+ onError?: (message: string) => void;
10
+ className?: string;
11
+ }
12
+ export declare const GeneralInformationCard: React.FC<GeneralInformationCardProps>;
@@ -0,0 +1,72 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as SDK from '@robosystems/client';
4
+ import { Button } from 'flowbite-react';
5
+ import { useState } from 'react';
6
+ import { HiUser } from 'react-icons/hi';
7
+ import { Spinner } from '../Spinner';
8
+ import { SettingsCard } from '../forms/SettingsCard';
9
+ import { SettingsFormField } from '../forms/SettingsFormField';
10
+ import { StatusAlert } from '../forms/StatusAlert';
11
+ export const GeneralInformationCard = ({ user, theme, onUpdate = undefined, onRefresh = undefined, onSuccess = undefined, onError = undefined, className = '', }) => {
12
+ const [isLoading, setIsLoading] = useState(false);
13
+ const [error, setError] = useState(null);
14
+ const [success, setSuccess] = useState(false);
15
+ const handleSubmit = async (event) => {
16
+ var _a, _b, _c;
17
+ event.preventDefault();
18
+ setError(null);
19
+ setSuccess(false);
20
+ const formData = new FormData(event.currentTarget);
21
+ const updateData = {
22
+ username: formData.get('username'),
23
+ email: formData.get('email'),
24
+ };
25
+ setIsLoading(true);
26
+ try {
27
+ if (onUpdate) {
28
+ await onUpdate(updateData);
29
+ }
30
+ else {
31
+ const response = await SDK.updateUser({
32
+ body: {
33
+ name: updateData.username,
34
+ email: updateData.email,
35
+ },
36
+ });
37
+ if (response.error) {
38
+ const detail = ((_b = (_a = response.error) === null || _a === void 0 ? void 0 : _a.detail) === null || _b === void 0 ? void 0 : _b.detail) ||
39
+ ((_c = response.error) === null || _c === void 0 ? void 0 : _c.detail) ||
40
+ 'Failed to update profile.';
41
+ throw new Error(typeof detail === 'string' ? detail : 'Failed to update profile.');
42
+ }
43
+ }
44
+ if (onSuccess) {
45
+ onSuccess('Profile updated successfully.');
46
+ }
47
+ else {
48
+ setSuccess(true);
49
+ }
50
+ if (onRefresh) {
51
+ await onRefresh();
52
+ }
53
+ setTimeout(() => {
54
+ setIsLoading(false);
55
+ setSuccess(false);
56
+ }, 2000);
57
+ }
58
+ catch (err) {
59
+ const msg = err instanceof Error && err.message
60
+ ? err.message
61
+ : 'Failed to update profile. Please try again.';
62
+ if (onError) {
63
+ onError(msg);
64
+ }
65
+ else {
66
+ setError(msg);
67
+ }
68
+ setIsLoading(false);
69
+ }
70
+ };
71
+ return (_jsxs(SettingsCard, { title: "General information", description: "Update your account details", icon: HiUser, theme: theme === null || theme === void 0 ? void 0 : theme.card, className: className, children: [_jsxs("div", { className: "space-y-4", children: [error && (_jsx(StatusAlert, { type: "error", message: error, theme: theme === null || theme === void 0 ? void 0 : theme.alert })), success && (_jsx(StatusAlert, { type: "success", message: "Profile updated successfully.", theme: theme === null || theme === void 0 ? void 0 : theme.alert }))] }), _jsx("form", { onSubmit: handleSubmit, children: _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "grid gap-4 md:grid-cols-2", children: [_jsx(SettingsFormField, { id: "username", label: "Username", placeholder: "Username", defaultValue: user.name, required: true, theme: theme }), _jsx(SettingsFormField, { id: "email", label: "Email", type: "email", placeholder: "Email", defaultValue: user.email, required: true, theme: theme })] }), _jsx("div", { className: "flex justify-end pt-2", children: _jsx(Button, { theme: theme === null || theme === void 0 ? void 0 : theme.button, color: "blue", type: "submit", disabled: isLoading, children: isLoading ? (_jsx(Spinner, { size: "sm", className: "text-white" })) : ('Save Changes') }) })] }) })] }));
72
+ };
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import type { PasswordUpdateData } from '../types';
3
+ export interface PasswordInformationCardProps {
4
+ theme?: any;
5
+ onUpdate?: (data: PasswordUpdateData) => Promise<void>;
6
+ onSuccess?: (message: string) => void;
7
+ onError?: (message: string) => void;
8
+ className?: string;
9
+ }
10
+ export declare const PasswordInformationCard: React.FC<PasswordInformationCardProps>;
@@ -0,0 +1,167 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as SDK from '@robosystems/client';
4
+ import { Button } from 'flowbite-react';
5
+ import { useCallback, useEffect, useRef, useState } from 'react';
6
+ import { HiLockClosed } from 'react-icons/hi';
7
+ import { Spinner } from '../Spinner';
8
+ import { SettingsCard } from '../forms/SettingsCard';
9
+ import { SettingsFormField } from '../forms/SettingsFormField';
10
+ import { StatusAlert } from '../forms/StatusAlert';
11
+ export const PasswordInformationCard = ({ theme, onUpdate = undefined, onSuccess = undefined, onError = undefined, className = '', }) => {
12
+ const [isLoading, setIsLoading] = useState(false);
13
+ const [error, setError] = useState(null);
14
+ const [success, setSuccess] = useState(false);
15
+ const [newPassword, setNewPassword] = useState('');
16
+ const [passwordStrength, setPasswordStrength] = useState(null);
17
+ const [checkingPassword, setCheckingPassword] = useState(false);
18
+ const debounceRef = useRef(null);
19
+ const checkPassword = useCallback(async (password) => {
20
+ if (password.length < 4) {
21
+ setPasswordStrength(null);
22
+ return;
23
+ }
24
+ setCheckingPassword(true);
25
+ try {
26
+ const response = await SDK.checkPasswordStrength({
27
+ body: { password },
28
+ });
29
+ const data = response.data;
30
+ setPasswordStrength({
31
+ score: (data === null || data === void 0 ? void 0 : data.score) || 0,
32
+ strength: (data === null || data === void 0 ? void 0 : data.strength) || 'very-weak',
33
+ errors: (data === null || data === void 0 ? void 0 : data.errors) || [],
34
+ suggestions: (data === null || data === void 0 ? void 0 : data.suggestions) || [],
35
+ is_valid: (data === null || data === void 0 ? void 0 : data.is_valid) || false,
36
+ });
37
+ }
38
+ catch (_a) {
39
+ setPasswordStrength(null);
40
+ }
41
+ finally {
42
+ setCheckingPassword(false);
43
+ }
44
+ }, []);
45
+ useEffect(() => {
46
+ if (debounceRef.current)
47
+ clearTimeout(debounceRef.current);
48
+ if (newPassword.length < 4) {
49
+ setPasswordStrength(null);
50
+ return;
51
+ }
52
+ debounceRef.current = setTimeout(() => {
53
+ checkPassword(newPassword);
54
+ }, 400);
55
+ return () => {
56
+ if (debounceRef.current)
57
+ clearTimeout(debounceRef.current);
58
+ };
59
+ }, [newPassword, checkPassword]);
60
+ const handleSubmit = async (event) => {
61
+ var _a, _b, _c;
62
+ event.preventDefault();
63
+ setError(null);
64
+ setSuccess(false);
65
+ const formData = new FormData(event.currentTarget);
66
+ const updateData = {
67
+ currentPassword: formData.get('currentPassword'),
68
+ newPassword: formData.get('newPassword'),
69
+ confirmPassword: formData.get('confirmPassword'),
70
+ };
71
+ // Client-side validation
72
+ if (updateData.newPassword !== updateData.confirmPassword) {
73
+ const msg = 'New password and confirmation do not match';
74
+ if (onError) {
75
+ onError(msg);
76
+ }
77
+ else {
78
+ setError(msg);
79
+ }
80
+ return;
81
+ }
82
+ if (checkingPassword) {
83
+ setError('Checking password strength, please wait...');
84
+ return;
85
+ }
86
+ if (passwordStrength && !passwordStrength.is_valid) {
87
+ const msg = passwordStrength.errors.length > 0
88
+ ? passwordStrength.errors.join('. ')
89
+ : 'Password does not meet requirements';
90
+ if (onError) {
91
+ onError(msg);
92
+ }
93
+ else {
94
+ setError(msg);
95
+ }
96
+ return;
97
+ }
98
+ setIsLoading(true);
99
+ const form = event.currentTarget;
100
+ try {
101
+ if (onUpdate) {
102
+ await onUpdate(updateData);
103
+ }
104
+ else {
105
+ const response = await SDK.updateUserPassword({
106
+ body: {
107
+ current_password: updateData.currentPassword,
108
+ new_password: updateData.newPassword,
109
+ confirm_password: updateData.confirmPassword,
110
+ },
111
+ });
112
+ if (response.error) {
113
+ const detail = ((_b = (_a = response.error) === null || _a === void 0 ? void 0 : _a.detail) === null || _b === void 0 ? void 0 : _b.detail) ||
114
+ ((_c = response.error) === null || _c === void 0 ? void 0 : _c.detail) ||
115
+ 'Failed to update password.';
116
+ throw new Error(typeof detail === 'string' ? detail : 'Failed to update password.');
117
+ }
118
+ }
119
+ if (onSuccess) {
120
+ onSuccess('Password updated successfully.');
121
+ }
122
+ else {
123
+ setSuccess(true);
124
+ }
125
+ // Clear form fields and strength state
126
+ form.reset();
127
+ setNewPassword('');
128
+ setPasswordStrength(null);
129
+ setTimeout(() => {
130
+ setIsLoading(false);
131
+ setSuccess(false);
132
+ }, 2000);
133
+ }
134
+ catch (err) {
135
+ const msg = err instanceof Error && err.message
136
+ ? err.message
137
+ : 'Failed to update password. Please try again.';
138
+ if (onError) {
139
+ onError(msg);
140
+ }
141
+ else {
142
+ setError(msg);
143
+ }
144
+ setIsLoading(false);
145
+ }
146
+ };
147
+ const strengthBarColor = !passwordStrength
148
+ ? ''
149
+ : passwordStrength.score < 30
150
+ ? 'bg-red-500'
151
+ : passwordStrength.score < 60
152
+ ? 'bg-yellow-500'
153
+ : passwordStrength.score < 80
154
+ ? 'bg-primary-400'
155
+ : 'bg-green-500';
156
+ const strengthTextColor = !passwordStrength
157
+ ? ''
158
+ : passwordStrength.score < 30
159
+ ? 'text-red-400'
160
+ : passwordStrength.score < 60
161
+ ? 'text-yellow-400'
162
+ : passwordStrength.score < 80
163
+ ? 'text-primary-300'
164
+ : 'text-green-400';
165
+ return (_jsxs(SettingsCard, { title: "Password information", description: "Update your password to keep your account secure", icon: HiLockClosed, theme: theme === null || theme === void 0 ? void 0 : theme.card, className: className, children: [_jsxs("div", { className: "space-y-4", children: [error && (_jsx(StatusAlert, { type: "error", message: error, theme: theme === null || theme === void 0 ? void 0 : theme.alert })), success && (_jsx(StatusAlert, { type: "success", message: "Password updated successfully.", theme: theme === null || theme === void 0 ? void 0 : theme.alert }))] }), _jsx("form", { onSubmit: handleSubmit, children: _jsxs("div", { className: "space-y-4", children: [_jsx("div", { className: "grid gap-4 md:grid-cols-2", children: _jsx(SettingsFormField, { id: "currentPassword", label: "Current password", type: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", theme: theme }) }), _jsxs("div", { className: "grid items-start gap-4 md:grid-cols-2", children: [_jsxs("div", { children: [_jsx(SettingsFormField, { id: "newPassword", label: "New password", type: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", theme: theme, onChange: (e) => setNewPassword(e.target.value) }), _jsx("div", { className: "mt-2 min-h-[2.75rem]", children: passwordStrength && (_jsxs("div", { className: "space-y-1.5", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "h-1.5 flex-1 overflow-hidden rounded-full bg-gray-700", children: _jsx("div", { className: `h-full rounded-full transition-all duration-300 ${strengthBarColor}`, style: { width: `${passwordStrength.score}%` } }) }), _jsx("span", { className: `text-xs font-medium capitalize ${strengthTextColor}`, children: passwordStrength.strength.replace('-', ' ') })] }), passwordStrength.errors.length > 0 && (_jsx("p", { className: "text-xs text-red-400", children: passwordStrength.errors[0] })), passwordStrength.errors.length === 0 &&
166
+ passwordStrength.suggestions.length > 0 && (_jsx("p", { className: "text-xs text-gray-400", children: passwordStrength.suggestions[0] }))] })) })] }), _jsx(SettingsFormField, { id: "confirmPassword", label: "Confirm password", type: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", theme: theme })] }), _jsx("div", { className: "flex justify-end pt-2", children: _jsx(Button, { theme: theme === null || theme === void 0 ? void 0 : theme.button, color: "blue", type: "submit", disabled: isLoading || checkingPassword, children: isLoading ? (_jsx(Spinner, { size: "sm", className: "text-white" })) : ('Update Password') }) })] }) })] }));
167
+ };
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ export interface SettingsPageHeaderProps {
3
+ title?: string;
4
+ homeHref?: string;
5
+ className?: string;
6
+ }
7
+ export declare const SettingsPageHeader: React.FC<SettingsPageHeaderProps>;
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Breadcrumb, BreadcrumbItem } from 'flowbite-react';
3
+ import { HiHome } from 'react-icons/hi';
4
+ export const SettingsPageHeader = ({ title = 'User settings', homeHref = '/home', className = '', }) => {
5
+ return (_jsxs("div", { className: `col-span-full mb-4 xl:mb-2 ${className}`, children: [_jsxs(Breadcrumb, { className: "mb-5", children: [_jsx(BreadcrumbItem, { href: homeHref, children: _jsxs("div", { className: "flex items-center gap-x-3", children: [_jsx(HiHome, { className: "text-xl" }), _jsx("span", { className: "dark:text-white", children: "Home" })] }) }), _jsx(BreadcrumbItem, { children: "Settings" })] }), _jsx("h1", { className: "text-xl font-semibold text-gray-900 sm:text-2xl dark:text-white", children: title })] }));
6
+ };
@@ -0,0 +1,3 @@
1
+ export { GeneralInformationCard } from './GeneralInformationCard';
2
+ export { PasswordInformationCard } from './PasswordInformationCard';
3
+ export { SettingsPageHeader } from './SettingsPageHeader';
@@ -0,0 +1,3 @@
1
+ export { GeneralInformationCard } from './GeneralInformationCard';
2
+ export { PasswordInformationCard } from './PasswordInformationCard';
3
+ export { SettingsPageHeader } from './SettingsPageHeader';
@@ -0,0 +1,15 @@
1
+ export interface SupportMetadata {
2
+ graphId?: string | null;
3
+ graphName?: string | null;
4
+ orgId?: string | null;
5
+ orgName?: string | null;
6
+ orgType?: string | null;
7
+ userRole?: string | null;
8
+ }
9
+ interface SupportModalProps {
10
+ isOpen: boolean;
11
+ onClose: () => void;
12
+ metadata?: SupportMetadata;
13
+ }
14
+ export default function SupportModal({ isOpen, onClose, metadata, }: SupportModalProps): import("react").JSX.Element;
15
+ export {};