@data-club/ai-hub 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/passwordPolicy.d.ts +55 -0
- package/dist/auth/passwordPolicy.d.ts.map +1 -0
- package/dist/auth/passwordPolicy.js +63 -0
- package/dist/auth/passwordPolicy.js.map +1 -0
- package/dist/auth/texts.d.ts +815 -0
- package/dist/auth/texts.d.ts.map +1 -0
- package/dist/auth/texts.js +429 -0
- package/dist/auth/texts.js.map +1 -0
- package/dist/client/AIHubClient.d.ts +1058 -0
- package/dist/client/AIHubClient.d.ts.map +1 -0
- package/dist/client/AIHubClient.js +950 -0
- package/dist/client/AIHubClient.js.map +1 -0
- package/dist/client/index.d.ts +11 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +9 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/sseParser.d.ts +41 -0
- package/dist/client/sseParser.d.ts.map +1 -0
- package/dist/client/sseParser.js +153 -0
- package/dist/client/sseParser.js.map +1 -0
- package/dist/client/tokenStorage.d.ts +56 -0
- package/dist/client/tokenStorage.d.ts.map +1 -0
- package/dist/client/tokenStorage.js +116 -0
- package/dist/client/tokenStorage.js.map +1 -0
- package/dist/components/AgentsPicker/index.d.ts +70 -0
- package/dist/components/AgentsPicker/index.d.ts.map +1 -0
- package/dist/components/AgentsPicker/index.js +63 -0
- package/dist/components/AgentsPicker/index.js.map +1 -0
- package/dist/components/AuthGate/index.d.ts +79 -0
- package/dist/components/AuthGate/index.d.ts.map +1 -0
- package/dist/components/AuthGate/index.js +61 -0
- package/dist/components/AuthGate/index.js.map +1 -0
- package/dist/components/CacheBadge/index.d.ts +88 -0
- package/dist/components/CacheBadge/index.d.ts.map +1 -0
- package/dist/components/CacheBadge/index.js +127 -0
- package/dist/components/CacheBadge/index.js.map +1 -0
- package/dist/components/ChangePassword/index.d.ts +109 -0
- package/dist/components/ChangePassword/index.d.ts.map +1 -0
- package/dist/components/ChangePassword/index.js +142 -0
- package/dist/components/ChangePassword/index.js.map +1 -0
- package/dist/components/ChatShell/ShellHeader.d.ts +44 -0
- package/dist/components/ChatShell/ShellHeader.d.ts.map +1 -0
- package/dist/components/ChatShell/ShellHeader.js +14 -0
- package/dist/components/ChatShell/ShellHeader.js.map +1 -0
- package/dist/components/ChatShell/UserMenu.d.ts +48 -0
- package/dist/components/ChatShell/UserMenu.d.ts.map +1 -0
- package/dist/components/ChatShell/UserMenu.js +86 -0
- package/dist/components/ChatShell/UserMenu.js.map +1 -0
- package/dist/components/ChatShell/index.d.ts +98 -0
- package/dist/components/ChatShell/index.d.ts.map +1 -0
- package/dist/components/ChatShell/index.js +124 -0
- package/dist/components/ChatShell/index.js.map +1 -0
- package/dist/components/DataClubAIHub/index.d.ts +132 -0
- package/dist/components/DataClubAIHub/index.d.ts.map +1 -0
- package/dist/components/DataClubAIHub/index.js +124 -0
- package/dist/components/DataClubAIHub/index.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/AgentEditorModal.d.ts +89 -0
- package/dist/components/DataClubAIHubAdmin/AgentEditorModal.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/AgentEditorModal.js +199 -0
- package/dist/components/DataClubAIHubAdmin/AgentEditorModal.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/AgentsPage.d.ts +33 -0
- package/dist/components/DataClubAIHubAdmin/AgentsPage.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/AgentsPage.js +137 -0
- package/dist/components/DataClubAIHubAdmin/AgentsPage.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/CreateUserModal.d.ts +50 -0
- package/dist/components/DataClubAIHubAdmin/CreateUserModal.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/CreateUserModal.js +93 -0
- package/dist/components/DataClubAIHubAdmin/CreateUserModal.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/PasswordRevealModal.d.ts +49 -0
- package/dist/components/DataClubAIHubAdmin/PasswordRevealModal.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/PasswordRevealModal.js +94 -0
- package/dist/components/DataClubAIHubAdmin/PasswordRevealModal.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/ResetPasswordModal.d.ts +37 -0
- package/dist/components/DataClubAIHubAdmin/ResetPasswordModal.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/ResetPasswordModal.js +44 -0
- package/dist/components/DataClubAIHubAdmin/ResetPasswordModal.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/RotatingMessageEditorModal.d.ts +56 -0
- package/dist/components/DataClubAIHubAdmin/RotatingMessageEditorModal.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/RotatingMessageEditorModal.js +158 -0
- package/dist/components/DataClubAIHubAdmin/RotatingMessageEditorModal.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/RotatingMessagesPage.d.ts +29 -0
- package/dist/components/DataClubAIHubAdmin/RotatingMessagesPage.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/RotatingMessagesPage.js +183 -0
- package/dist/components/DataClubAIHubAdmin/RotatingMessagesPage.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/SessionsOverviewPage.d.ts +38 -0
- package/dist/components/DataClubAIHubAdmin/SessionsOverviewPage.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/SessionsOverviewPage.js +294 -0
- package/dist/components/DataClubAIHubAdmin/SessionsOverviewPage.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/SettingsPage.d.ts +36 -0
- package/dist/components/DataClubAIHubAdmin/SettingsPage.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/SettingsPage.js +373 -0
- package/dist/components/DataClubAIHubAdmin/SettingsPage.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/UsersPage.d.ts +47 -0
- package/dist/components/DataClubAIHubAdmin/UsersPage.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/UsersPage.js +233 -0
- package/dist/components/DataClubAIHubAdmin/UsersPage.js.map +1 -0
- package/dist/components/DataClubAIHubAdmin/index.d.ts +87 -0
- package/dist/components/DataClubAIHubAdmin/index.d.ts.map +1 -0
- package/dist/components/DataClubAIHubAdmin/index.js +137 -0
- package/dist/components/DataClubAIHubAdmin/index.js.map +1 -0
- package/dist/components/DataClubAIHubLogin/index.d.ts +113 -0
- package/dist/components/DataClubAIHubLogin/index.d.ts.map +1 -0
- package/dist/components/DataClubAIHubLogin/index.js +123 -0
- package/dist/components/DataClubAIHubLogin/index.js.map +1 -0
- package/dist/components/EffortControl/index.d.ts +57 -0
- package/dist/components/EffortControl/index.d.ts.map +1 -0
- package/dist/components/EffortControl/index.js +84 -0
- package/dist/components/EffortControl/index.js.map +1 -0
- package/dist/components/Layout/index.d.ts +63 -0
- package/dist/components/Layout/index.d.ts.map +1 -0
- package/dist/components/Layout/index.js +45 -0
- package/dist/components/Layout/index.js.map +1 -0
- package/dist/components/MainColumn/index.d.ts +69 -0
- package/dist/components/MainColumn/index.d.ts.map +1 -0
- package/dist/components/MainColumn/index.js +47 -0
- package/dist/components/MainColumn/index.js.map +1 -0
- package/dist/components/MarkdownRenderer/index.d.ts +66 -0
- package/dist/components/MarkdownRenderer/index.d.ts.map +1 -0
- package/dist/components/MarkdownRenderer/index.js +153 -0
- package/dist/components/MarkdownRenderer/index.js.map +1 -0
- package/dist/components/MessageInput/index.d.ts +85 -0
- package/dist/components/MessageInput/index.d.ts.map +1 -0
- package/dist/components/MessageInput/index.js +139 -0
- package/dist/components/MessageInput/index.js.map +1 -0
- package/dist/components/MessageList/index.d.ts +156 -0
- package/dist/components/MessageList/index.d.ts.map +1 -0
- package/dist/components/MessageList/index.js +352 -0
- package/dist/components/MessageList/index.js.map +1 -0
- package/dist/components/ReasoningSelector/index.d.ts +77 -0
- package/dist/components/ReasoningSelector/index.d.ts.map +1 -0
- package/dist/components/ReasoningSelector/index.js +156 -0
- package/dist/components/ReasoningSelector/index.js.map +1 -0
- package/dist/components/ReasoningView/index.d.ts +94 -0
- package/dist/components/ReasoningView/index.d.ts.map +1 -0
- package/dist/components/ReasoningView/index.js +83 -0
- package/dist/components/ReasoningView/index.js.map +1 -0
- package/dist/components/ScrollToPresentButton/index.d.ts +54 -0
- package/dist/components/ScrollToPresentButton/index.d.ts.map +1 -0
- package/dist/components/ScrollToPresentButton/index.js +44 -0
- package/dist/components/ScrollToPresentButton/index.js.map +1 -0
- package/dist/components/SessionsPanel/SessionTitleModal.d.ts +79 -0
- package/dist/components/SessionsPanel/SessionTitleModal.d.ts.map +1 -0
- package/dist/components/SessionsPanel/SessionTitleModal.js +102 -0
- package/dist/components/SessionsPanel/SessionTitleModal.js.map +1 -0
- package/dist/components/SessionsPanel/index.d.ts +100 -0
- package/dist/components/SessionsPanel/index.d.ts.map +1 -0
- package/dist/components/SessionsPanel/index.js +176 -0
- package/dist/components/SessionsPanel/index.js.map +1 -0
- package/dist/components/SystemNotice/index.d.ts +66 -0
- package/dist/components/SystemNotice/index.d.ts.map +1 -0
- package/dist/components/SystemNotice/index.js +81 -0
- package/dist/components/SystemNotice/index.js.map +1 -0
- package/dist/components/ThemeSwitcher/index.d.ts +66 -0
- package/dist/components/ThemeSwitcher/index.d.ts.map +1 -0
- package/dist/components/ThemeSwitcher/index.js +73 -0
- package/dist/components/ThemeSwitcher/index.js.map +1 -0
- package/dist/components/ToolCallView/formatContent.d.ts +36 -0
- package/dist/components/ToolCallView/formatContent.d.ts.map +1 -0
- package/dist/components/ToolCallView/formatContent.js +53 -0
- package/dist/components/ToolCallView/formatContent.js.map +1 -0
- package/dist/components/ToolCallView/index.d.ts +120 -0
- package/dist/components/ToolCallView/index.d.ts.map +1 -0
- package/dist/components/ToolCallView/index.js +104 -0
- package/dist/components/ToolCallView/index.js.map +1 -0
- package/dist/components/TpmBanner/index.d.ts +53 -0
- package/dist/components/TpmBanner/index.d.ts.map +1 -0
- package/dist/components/TpmBanner/index.js +116 -0
- package/dist/components/TpmBanner/index.js.map +1 -0
- package/dist/components/TurnStatusIndicator/index.d.ts +77 -0
- package/dist/components/TurnStatusIndicator/index.d.ts.map +1 -0
- package/dist/components/TurnStatusIndicator/index.js +122 -0
- package/dist/components/TurnStatusIndicator/index.js.map +1 -0
- package/dist/components/internal/PasswordInput.d.ts +62 -0
- package/dist/components/internal/PasswordInput.d.ts.map +1 -0
- package/dist/components/internal/PasswordInput.js +42 -0
- package/dist/components/internal/PasswordInput.js.map +1 -0
- package/dist/context/AIHubContext.d.ts +220 -0
- package/dist/context/AIHubContext.d.ts.map +1 -0
- package/dist/context/AIHubContext.js +19 -0
- package/dist/context/AIHubContext.js.map +1 -0
- package/dist/context/AIHubProvider.d.ts +75 -0
- package/dist/context/AIHubProvider.d.ts.map +1 -0
- package/dist/context/AIHubProvider.js +954 -0
- package/dist/context/AIHubProvider.js.map +1 -0
- package/dist/context/index.d.ts +9 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +9 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/theme.d.ts +43 -0
- package/dist/context/theme.d.ts.map +1 -0
- package/dist/context/theme.js +70 -0
- package/dist/context/theme.js.map +1 -0
- package/dist/context/useAIHub.d.ts +104 -0
- package/dist/context/useAIHub.d.ts.map +1 -0
- package/dist/context/useAIHub.js +63 -0
- package/dist/context/useAIHub.js.map +1 -0
- package/dist/context/useAIHubAuth.d.ts +44 -0
- package/dist/context/useAIHubAuth.d.ts.map +1 -0
- package/dist/context/useAIHubAuth.js +35 -0
- package/dist/context/useAIHubAuth.js.map +1 -0
- package/dist/index.d.ts +76 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/primitives/index.d.ts +99 -0
- package/dist/primitives/index.d.ts.map +1 -0
- package/dist/primitives/index.js +97 -0
- package/dist/primitives/index.js.map +1 -0
- package/dist/state/affordances.d.ts +182 -0
- package/dist/state/affordances.d.ts.map +1 -0
- package/dist/state/affordances.js +189 -0
- package/dist/state/affordances.js.map +1 -0
- package/dist/state/stateReducer.d.ts +72 -0
- package/dist/state/stateReducer.d.ts.map +1 -0
- package/dist/state/stateReducer.js +122 -0
- package/dist/state/stateReducer.js.map +1 -0
- package/dist/stories/EffortControl.stories.d.ts +14 -0
- package/dist/stories/EffortControl.stories.d.ts.map +1 -0
- package/dist/stories/EffortControl.stories.js +43 -0
- package/dist/stories/EffortControl.stories.js.map +1 -0
- package/dist/stories/MarkdownRenderer.stories.d.ts +25 -0
- package/dist/stories/MarkdownRenderer.stories.d.ts.map +1 -0
- package/dist/stories/MarkdownRenderer.stories.js +178 -0
- package/dist/stories/MarkdownRenderer.stories.js.map +1 -0
- package/dist/stories/MessageBubble.stories.d.ts +21 -0
- package/dist/stories/MessageBubble.stories.d.ts.map +1 -0
- package/dist/stories/MessageBubble.stories.js +59 -0
- package/dist/stories/MessageBubble.stories.js.map +1 -0
- package/dist/stories/ReasoningView.stories.d.ts +18 -0
- package/dist/stories/ReasoningView.stories.d.ts.map +1 -0
- package/dist/stories/ReasoningView.stories.js +62 -0
- package/dist/stories/ReasoningView.stories.js.map +1 -0
- package/dist/stories/ScrollToPresentButton.stories.d.ts +18 -0
- package/dist/stories/ScrollToPresentButton.stories.d.ts.map +1 -0
- package/dist/stories/ScrollToPresentButton.stories.js +34 -0
- package/dist/stories/ScrollToPresentButton.stories.js.map +1 -0
- package/dist/stories/SystemNotice.stories.d.ts +17 -0
- package/dist/stories/SystemNotice.stories.d.ts.map +1 -0
- package/dist/stories/SystemNotice.stories.js +42 -0
- package/dist/stories/SystemNotice.stories.js.map +1 -0
- package/dist/stories/ThemeSwitcher.stories.d.ts +15 -0
- package/dist/stories/ThemeSwitcher.stories.d.ts.map +1 -0
- package/dist/stories/ThemeSwitcher.stories.js +35 -0
- package/dist/stories/ThemeSwitcher.stories.js.map +1 -0
- package/dist/stories/ToolCallView.stories.d.ts +20 -0
- package/dist/stories/ToolCallView.stories.d.ts.map +1 -0
- package/dist/stories/ToolCallView.stories.js +65 -0
- package/dist/stories/ToolCallView.stories.js.map +1 -0
- package/dist/stories/TpmBanner.stories.d.ts +24 -0
- package/dist/stories/TpmBanner.stories.d.ts.map +1 -0
- package/dist/stories/TpmBanner.stories.js +63 -0
- package/dist/stories/TpmBanner.stories.js.map +1 -0
- package/dist/stories/TurnStatusIndicator.stories.d.ts +25 -0
- package/dist/stories/TurnStatusIndicator.stories.d.ts.map +1 -0
- package/dist/stories/TurnStatusIndicator.stories.js +56 -0
- package/dist/stories/TurnStatusIndicator.stories.js.map +1 -0
- package/dist/stories/_mockProvider.d.ts +44 -0
- package/dist/stories/_mockProvider.d.ts.map +1 -0
- package/dist/stories/_mockProvider.js +84 -0
- package/dist/stories/_mockProvider.js.map +1 -0
- package/dist/types.d.ts +787 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/dist/webcomponent/defineWebComponent.d.ts +106 -0
- package/dist/webcomponent/defineWebComponent.d.ts.map +1 -0
- package/dist/webcomponent/defineWebComponent.js +126 -0
- package/dist/webcomponent/defineWebComponent.js.map +1 -0
- package/dist/webcomponent/index.d.ts +7 -0
- package/dist/webcomponent/index.d.ts.map +1 -0
- package/dist/webcomponent/index.js +7 -0
- package/dist/webcomponent/index.js.map +1 -0
- package/package.json +63 -0
- package/src/__lint-canary__/step1-lint-canary.ts.disabled +28 -0
- package/src/auth/passwordPolicy.ts +75 -0
- package/src/auth/texts.ts +1294 -0
- package/src/client/AIHubClient.ts +1718 -0
- package/src/client/index.ts +30 -0
- package/src/client/sseParser.ts +168 -0
- package/src/client/tokenStorage.ts +131 -0
- package/src/components/AgentsPicker/index.tsx +147 -0
- package/src/components/AuthGate/index.tsx +132 -0
- package/src/components/CacheBadge/index.tsx +245 -0
- package/src/components/ChangePassword/index.tsx +375 -0
- package/src/components/ChatShell/ShellHeader.tsx +80 -0
- package/src/components/ChatShell/UserMenu.tsx +196 -0
- package/src/components/ChatShell/index.tsx +307 -0
- package/src/components/DataClubAIHub/index.tsx +300 -0
- package/src/components/DataClubAIHubAdmin/AgentEditorModal.tsx +505 -0
- package/src/components/DataClubAIHubAdmin/AgentsPage.tsx +342 -0
- package/src/components/DataClubAIHubAdmin/CreateUserModal.tsx +214 -0
- package/src/components/DataClubAIHubAdmin/PasswordRevealModal.tsx +204 -0
- package/src/components/DataClubAIHubAdmin/ResetPasswordModal.tsx +122 -0
- package/src/components/DataClubAIHubAdmin/RotatingMessageEditorModal.tsx +408 -0
- package/src/components/DataClubAIHubAdmin/RotatingMessagesPage.tsx +373 -0
- package/src/components/DataClubAIHubAdmin/SessionsOverviewPage.tsx +639 -0
- package/src/components/DataClubAIHubAdmin/SettingsPage.tsx +979 -0
- package/src/components/DataClubAIHubAdmin/UsersPage.tsx +495 -0
- package/src/components/DataClubAIHubAdmin/index.tsx +277 -0
- package/src/components/DataClubAIHubLogin/index.tsx +282 -0
- package/src/components/EffortControl/index.tsx +138 -0
- package/src/components/Layout/index.tsx +92 -0
- package/src/components/MainColumn/index.tsx +131 -0
- package/src/components/MarkdownRenderer/index.tsx +256 -0
- package/src/components/MessageInput/index.tsx +283 -0
- package/src/components/MessageList/index.tsx +753 -0
- package/src/components/ReasoningSelector/index.tsx +268 -0
- package/src/components/ReasoningView/index.tsx +183 -0
- package/src/components/ScrollToPresentButton/index.tsx +85 -0
- package/src/components/SessionsPanel/SessionTitleModal.tsx +256 -0
- package/src/components/SessionsPanel/index.tsx +406 -0
- package/src/components/SystemNotice/index.tsx +151 -0
- package/src/components/ThemeSwitcher/index.tsx +136 -0
- package/src/components/ToolCallView/formatContent.ts +50 -0
- package/src/components/ToolCallView/index.tsx +274 -0
- package/src/components/TpmBanner/index.tsx +172 -0
- package/src/components/TurnStatusIndicator/index.tsx +203 -0
- package/src/components/internal/PasswordInput.tsx +145 -0
- package/src/context/AIHubContext.ts +249 -0
- package/src/context/AIHubProvider.tsx +1084 -0
- package/src/context/index.ts +9 -0
- package/src/context/theme.ts +76 -0
- package/src/context/useAIHub.ts +151 -0
- package/src/context/useAIHubAuth.ts +65 -0
- package/src/index.ts +275 -0
- package/src/primitives/index.ts +101 -0
- package/src/state/affordances.ts +321 -0
- package/src/state/stateReducer.ts +131 -0
- package/src/stories/EffortControl.stories.tsx +63 -0
- package/src/stories/MarkdownRenderer.stories.tsx +201 -0
- package/src/stories/MessageBubble.stories.tsx +101 -0
- package/src/stories/ReasoningView.stories.tsx +81 -0
- package/src/stories/ScrollToPresentButton.stories.tsx +52 -0
- package/src/stories/SystemNotice.stories.tsx +59 -0
- package/src/stories/ThemeSwitcher.stories.tsx +55 -0
- package/src/stories/ToolCallView.stories.tsx +95 -0
- package/src/stories/TpmBanner.stories.tsx +93 -0
- package/src/stories/TurnStatusIndicator.stories.tsx +86 -0
- package/src/stories/_mockProvider.tsx +116 -0
- package/src/styles/CLASSES.md +356 -0
- package/src/styles/default.css +2937 -0
- package/src/types.ts +867 -0
- package/src/webcomponent/defineWebComponent.tsx +193 -0
- package/src/webcomponent/index.ts +11 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<Layout />` — the flex container holding the sessions panel beside the
|
|
3
|
+
* main column.
|
|
4
|
+
*
|
|
5
|
+
* The default monolith puts the sessions panel on the left at 25% width;
|
|
6
|
+
* Tier 3 wrappers use this primitive directly to flip the position
|
|
7
|
+
* (`panelPosition="right"`) or to drop the panel entirely.
|
|
8
|
+
*
|
|
9
|
+
* Exported under `AIHub.Layout`.
|
|
10
|
+
*
|
|
11
|
+
* @see SPECIFICATIONS.md §7.1 — exports
|
|
12
|
+
* @see SPECIFICATIONS.md §7.9 — Tier-3 composition
|
|
13
|
+
* @see ui-sketches/03-chat.md — sessions_panel + main_column
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { type CSSProperties, type ReactNode } from "react";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* BEM class names emitted by `<Layout />`. The class names react to the
|
|
20
|
+
* `panelPosition` prop via a single modifier on the root.
|
|
21
|
+
*/
|
|
22
|
+
export interface LayoutClassNames {
|
|
23
|
+
/** Outer flex container. */
|
|
24
|
+
root: string;
|
|
25
|
+
/** Modifier appended when `panelPosition === "left"` (default). */
|
|
26
|
+
rootPanelLeft: string;
|
|
27
|
+
/** Modifier appended when `panelPosition === "right"`. */
|
|
28
|
+
rootPanelRight: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const DEFAULT_CLASS_NAMES: LayoutClassNames = Object.freeze({
|
|
32
|
+
root: "data-club-ai-hub__layout",
|
|
33
|
+
rootPanelLeft: "data-club-ai-hub__layout--panel-left",
|
|
34
|
+
rootPanelRight: "data-club-ai-hub__layout--panel-right",
|
|
35
|
+
}) as LayoutClassNames;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Props for `<Layout />`.
|
|
39
|
+
*/
|
|
40
|
+
export interface LayoutProps {
|
|
41
|
+
/**
|
|
42
|
+
* Which side the sessions panel sits on. Defaults to `"left"`.
|
|
43
|
+
* `<DataClubAIHub />` forwards its `sessionsPanelPosition` prop here.
|
|
44
|
+
*/
|
|
45
|
+
panelPosition?: "left" | "right";
|
|
46
|
+
/**
|
|
47
|
+
* Sessions panel width in percent. Defaults to `25`. Layout only uses
|
|
48
|
+
* this for the CSS custom property `--dc-aih-sessions-panel-width`;
|
|
49
|
+
* the panel itself reads it.
|
|
50
|
+
*/
|
|
51
|
+
panelWidthPercent?: number;
|
|
52
|
+
/** Extra className merged onto the root. */
|
|
53
|
+
className?: string;
|
|
54
|
+
/** Per-element class overrides. */
|
|
55
|
+
classNames?: Partial<LayoutClassNames>;
|
|
56
|
+
/**
|
|
57
|
+
* Children — typically `<SessionsPanel />` and `<MainColumn />` in
|
|
58
|
+
* either order; this primitive trusts the caller to put them in DOM
|
|
59
|
+
* order. The `panelPosition` modifier flips the visual order via
|
|
60
|
+
* `flex-direction: row-reverse` in CSS, so the sessions panel is
|
|
61
|
+
* always rendered first in the DOM regardless.
|
|
62
|
+
*/
|
|
63
|
+
children: ReactNode;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Renders the layout container.
|
|
68
|
+
*
|
|
69
|
+
* @param props - see `LayoutProps`.
|
|
70
|
+
* @returns the rendered layout.
|
|
71
|
+
*/
|
|
72
|
+
export function Layout(props: LayoutProps): ReactNode {
|
|
73
|
+
const cls = { ...DEFAULT_CLASS_NAMES, ...(props.classNames ?? {}) };
|
|
74
|
+
const position = props.panelPosition ?? "left";
|
|
75
|
+
const widthPercent = props.panelWidthPercent ?? 25;
|
|
76
|
+
const rootClasses = [
|
|
77
|
+
cls.root,
|
|
78
|
+
position === "right" ? cls.rootPanelRight : cls.rootPanelLeft,
|
|
79
|
+
props.className,
|
|
80
|
+
]
|
|
81
|
+
.filter(Boolean)
|
|
82
|
+
.join(" ");
|
|
83
|
+
const style: CSSProperties = {
|
|
84
|
+
// Custom property consumed by the sessions panel.
|
|
85
|
+
["--dc-aih-sessions-panel-width" as keyof CSSProperties]: `${widthPercent}%`,
|
|
86
|
+
} as CSSProperties;
|
|
87
|
+
return (
|
|
88
|
+
<div className={rootClasses} data-testid="layout" style={style}>
|
|
89
|
+
{props.children}
|
|
90
|
+
</div>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<MainColumn />` — the right side of the chat layout: chat header on
|
|
3
|
+
* top, scrollable message list in the middle, input area on the bottom.
|
|
4
|
+
*
|
|
5
|
+
* Step 10 mounts `<TurnStatusIndicator />` in the chat header to the right
|
|
6
|
+
* of the agent display name (gated by `showTurnStatus`, which the
|
|
7
|
+
* upstream §8.4 resolver passes in as a boolean prop). The
|
|
8
|
+
* `customHeaderContent` slot remains the wrapper-owned right-side slot
|
|
9
|
+
* (rendered after the turn-status indicator).
|
|
10
|
+
*
|
|
11
|
+
* Exported under `AIHub.MainColumn`.
|
|
12
|
+
*
|
|
13
|
+
* @see SPECIFICATIONS.md §7.1 — exports
|
|
14
|
+
* @see ui-sketches/03-chat.md — main_column + chat_header
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { useMemo, type ReactNode } from "react";
|
|
18
|
+
|
|
19
|
+
import {
|
|
20
|
+
resolveAIHubTexts,
|
|
21
|
+
type AIHubTexts,
|
|
22
|
+
type DeepPartial,
|
|
23
|
+
} from "../../auth/texts.js";
|
|
24
|
+
import { useAIHub } from "../../context/useAIHub.js";
|
|
25
|
+
|
|
26
|
+
import { TurnStatusIndicator } from "../TurnStatusIndicator/index.js";
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* BEM class names emitted by `<MainColumn />`.
|
|
30
|
+
*/
|
|
31
|
+
export interface MainColumnClassNames {
|
|
32
|
+
/** Outer column. */
|
|
33
|
+
root: string;
|
|
34
|
+
/** Chat header strip at the top. */
|
|
35
|
+
header: string;
|
|
36
|
+
/** Back-to-agents-picker link. */
|
|
37
|
+
back: string;
|
|
38
|
+
/** Agent display-name text. */
|
|
39
|
+
title: string;
|
|
40
|
+
/** Wrapper for slot content on the right side of the header. */
|
|
41
|
+
extras: string;
|
|
42
|
+
/** Children container (messages + input live here). */
|
|
43
|
+
body: string;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const DEFAULT_CLASS_NAMES: MainColumnClassNames = Object.freeze({
|
|
47
|
+
root: "data-club-ai-hub__main-column",
|
|
48
|
+
header: "data-club-ai-hub__chat-header",
|
|
49
|
+
back: "data-club-ai-hub__chat-header__back",
|
|
50
|
+
title: "data-club-ai-hub__chat-header__title",
|
|
51
|
+
extras: "data-club-ai-hub__chat-header__extras",
|
|
52
|
+
body: "data-club-ai-hub__main-column__body",
|
|
53
|
+
}) as MainColumnClassNames;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Props for `<MainColumn />`.
|
|
57
|
+
*/
|
|
58
|
+
export interface MainColumnProps {
|
|
59
|
+
/**
|
|
60
|
+
* Whether the back link to the agents picker is shown. Controlled by
|
|
61
|
+
* `<DataClubAIHub />`'s `showAgentsPicker` prop (the monolith hides
|
|
62
|
+
* the link in single-agent embeds). Defaults to true.
|
|
63
|
+
*/
|
|
64
|
+
showBackToAgents?: boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Whether to mount the turn-status indicator in the chat header.
|
|
67
|
+
* Receives the resolved §8.4 flag stack (server toggle > prop >
|
|
68
|
+
* default). Defaults to true.
|
|
69
|
+
*/
|
|
70
|
+
showTurnStatus?: boolean;
|
|
71
|
+
/** Slot rendered on the right side of the chat header. */
|
|
72
|
+
customHeaderContent?: ReactNode;
|
|
73
|
+
/** The children — `<MessageList />` + `<MessageInput />` (or whatever). */
|
|
74
|
+
children: ReactNode;
|
|
75
|
+
/** Extra class merged onto the root. */
|
|
76
|
+
className?: string;
|
|
77
|
+
/** Per-element class overrides. */
|
|
78
|
+
classNames?: Partial<MainColumnClassNames>;
|
|
79
|
+
/** Wrapper-supplied i18n. */
|
|
80
|
+
texts?: DeepPartial<AIHubTexts>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Renders the main column.
|
|
85
|
+
*
|
|
86
|
+
* @param props - see `MainColumnProps`.
|
|
87
|
+
* @returns the rendered column.
|
|
88
|
+
*/
|
|
89
|
+
export function MainColumn(props: MainColumnProps): ReactNode {
|
|
90
|
+
const { agents, activeAgentId, setActiveAgent } = useAIHub();
|
|
91
|
+
const texts = resolveAIHubTexts(props.texts);
|
|
92
|
+
const cls = { ...DEFAULT_CLASS_NAMES, ...(props.classNames ?? {}) };
|
|
93
|
+
const showBack = props.showBackToAgents ?? true;
|
|
94
|
+
const showTurnStatus = props.showTurnStatus ?? true;
|
|
95
|
+
|
|
96
|
+
const activeAgent = useMemo(
|
|
97
|
+
() => agents.find((a) => a.id === activeAgentId) ?? null,
|
|
98
|
+
[agents, activeAgentId],
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
const rootClass = props.className
|
|
102
|
+
? `${cls.root} ${props.className}`
|
|
103
|
+
: cls.root;
|
|
104
|
+
|
|
105
|
+
return (
|
|
106
|
+
<section className={rootClass} data-testid="main-column">
|
|
107
|
+
<header className={cls.header} data-testid="chat-header">
|
|
108
|
+
{showBack ? (
|
|
109
|
+
<button
|
|
110
|
+
type="button"
|
|
111
|
+
className={cls.back}
|
|
112
|
+
onClick={() => setActiveAgent(null)}
|
|
113
|
+
data-testid="chat-header-back"
|
|
114
|
+
>
|
|
115
|
+
{texts.chat.backToAgentsLink}
|
|
116
|
+
</button>
|
|
117
|
+
) : null}
|
|
118
|
+
<h2 className={cls.title} data-testid="chat-header-title">
|
|
119
|
+
{activeAgent?.display_name ?? ""}
|
|
120
|
+
</h2>
|
|
121
|
+
{showTurnStatus ? <TurnStatusIndicator /> : null}
|
|
122
|
+
{props.customHeaderContent ? (
|
|
123
|
+
<div className={cls.extras} data-testid="chat-header-extras">
|
|
124
|
+
{props.customHeaderContent}
|
|
125
|
+
</div>
|
|
126
|
+
) : null}
|
|
127
|
+
</header>
|
|
128
|
+
<div className={cls.body}>{props.children}</div>
|
|
129
|
+
</section>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<MarkdownRenderer />` — renders the textual body of an assistant
|
|
3
|
+
* message as GitHub-flavored Markdown with LaTeX-style math.
|
|
4
|
+
*
|
|
5
|
+
* The plumbing is the de-facto standard for AI chat output:
|
|
6
|
+
*
|
|
7
|
+
* - `react-markdown` parses the source into a hast (HTML AST) tree.
|
|
8
|
+
* - `remark-gfm` adds GitHub-flavored extensions on the mdast (markdown
|
|
9
|
+
* AST) side: pipe tables, task lists, strikethrough, autolinked URLs.
|
|
10
|
+
* - `remark-math` recognises `$inline$` and `$$block$$` LaTeX-style
|
|
11
|
+
* math, leaving it as an inline / block math node in mdast.
|
|
12
|
+
* - `rehype-katex` walks the hast tree and replaces those math nodes
|
|
13
|
+
* with rendered KaTeX HTML; consumers MUST also import
|
|
14
|
+
* `katex/dist/katex.min.css` (the chat shell's stylesheet bundles
|
|
15
|
+
* it — see `src/styles/default.css`) for the equations to look right.
|
|
16
|
+
*
|
|
17
|
+
* Every node we override emits a BEM-style class under
|
|
18
|
+
* `data-club-ai-hub__markdown__*`. The default stylesheet themes those
|
|
19
|
+
* via `--dc-aih-*` custom properties so per-customer wrappers keep
|
|
20
|
+
* working without touching this component.
|
|
21
|
+
*
|
|
22
|
+
* @see SPECIFICATIONS.md §7.3 — message bubble variants
|
|
23
|
+
* @see docs/react/markdown-rendering.md
|
|
24
|
+
*/
|
|
25
|
+
import ReactMarkdown from "react-markdown";
|
|
26
|
+
import remarkGfm from "remark-gfm";
|
|
27
|
+
import remarkMath from "remark-math";
|
|
28
|
+
import rehypeKatex from "rehype-katex";
|
|
29
|
+
import type { Components } from "react-markdown";
|
|
30
|
+
import type { ReactNode } from "react";
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* BEM class names emitted by `<MarkdownRenderer />`.
|
|
34
|
+
*
|
|
35
|
+
* Every element a markdown document can produce gets a stable class so
|
|
36
|
+
* per-customer wrappers can override individual pieces (e.g. brand the
|
|
37
|
+
* table border without touching the surrounding bubble).
|
|
38
|
+
*/
|
|
39
|
+
export interface MarkdownRendererClassNames {
|
|
40
|
+
/** Wrapper around the rendered markdown tree. */
|
|
41
|
+
root: string;
|
|
42
|
+
/** `<p>` paragraph. */
|
|
43
|
+
paragraph: string;
|
|
44
|
+
/** `<h1>` — `<h6>` headings. */
|
|
45
|
+
heading: string;
|
|
46
|
+
/** `<ul>` unordered list. */
|
|
47
|
+
ul: string;
|
|
48
|
+
/** `<ol>` ordered list. */
|
|
49
|
+
ol: string;
|
|
50
|
+
/** `<li>` list item. */
|
|
51
|
+
li: string;
|
|
52
|
+
/** `<a>` link. */
|
|
53
|
+
link: string;
|
|
54
|
+
/** `<blockquote>`. */
|
|
55
|
+
blockquote: string;
|
|
56
|
+
/** `<hr>` horizontal rule. */
|
|
57
|
+
hr: string;
|
|
58
|
+
/** Inline `<code>` (within a paragraph). */
|
|
59
|
+
inlineCode: string;
|
|
60
|
+
/** Fenced code block — the `<pre>` wrapper. */
|
|
61
|
+
codeBlock: string;
|
|
62
|
+
/** Wrapping `<div>` around `<table>` (horizontal-scroll container). */
|
|
63
|
+
tableWrapper: string;
|
|
64
|
+
/** The `<table>` itself. */
|
|
65
|
+
table: string;
|
|
66
|
+
/** `<thead>`. */
|
|
67
|
+
thead: string;
|
|
68
|
+
/** `<tbody>`. */
|
|
69
|
+
tbody: string;
|
|
70
|
+
/** `<tr>`. */
|
|
71
|
+
tr: string;
|
|
72
|
+
/** `<th>` header cell. */
|
|
73
|
+
th: string;
|
|
74
|
+
/** `<td>` body cell. */
|
|
75
|
+
td: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const DEFAULT_CLASS_NAMES: MarkdownRendererClassNames = Object.freeze({
|
|
79
|
+
root: "data-club-ai-hub__markdown",
|
|
80
|
+
paragraph: "data-club-ai-hub__markdown__p",
|
|
81
|
+
heading: "data-club-ai-hub__markdown__heading",
|
|
82
|
+
ul: "data-club-ai-hub__markdown__ul",
|
|
83
|
+
ol: "data-club-ai-hub__markdown__ol",
|
|
84
|
+
li: "data-club-ai-hub__markdown__li",
|
|
85
|
+
link: "data-club-ai-hub__markdown__a",
|
|
86
|
+
blockquote: "data-club-ai-hub__markdown__blockquote",
|
|
87
|
+
hr: "data-club-ai-hub__markdown__hr",
|
|
88
|
+
inlineCode: "data-club-ai-hub__markdown__code--inline",
|
|
89
|
+
codeBlock: "data-club-ai-hub__markdown__pre",
|
|
90
|
+
tableWrapper: "data-club-ai-hub__markdown__table-wrapper",
|
|
91
|
+
table: "data-club-ai-hub__markdown__table",
|
|
92
|
+
thead: "data-club-ai-hub__markdown__thead",
|
|
93
|
+
tbody: "data-club-ai-hub__markdown__tbody",
|
|
94
|
+
tr: "data-club-ai-hub__markdown__tr",
|
|
95
|
+
th: "data-club-ai-hub__markdown__th",
|
|
96
|
+
td: "data-club-ai-hub__markdown__td",
|
|
97
|
+
}) as MarkdownRendererClassNames;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Props for `<MarkdownRenderer />`.
|
|
101
|
+
*/
|
|
102
|
+
export interface MarkdownRendererProps {
|
|
103
|
+
/** Raw markdown source. Empty / whitespace-only input renders nothing. */
|
|
104
|
+
content: string;
|
|
105
|
+
/** Extra class merged onto the root. */
|
|
106
|
+
className?: string;
|
|
107
|
+
/** Per-element class overrides. */
|
|
108
|
+
classNames?: Partial<MarkdownRendererClassNames>;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Build the `react-markdown` component overrides table. Pulled out of
|
|
113
|
+
* the render body so the closure captures only `cls` (cheap to recreate)
|
|
114
|
+
* and the JSX inside is uncluttered.
|
|
115
|
+
*/
|
|
116
|
+
function buildComponents(cls: MarkdownRendererClassNames): Components {
|
|
117
|
+
return {
|
|
118
|
+
p({ children }) {
|
|
119
|
+
return <p className={cls.paragraph}>{children}</p>;
|
|
120
|
+
},
|
|
121
|
+
h1({ children }) {
|
|
122
|
+
return (
|
|
123
|
+
<h1 className={`${cls.heading} ${cls.heading}--1`}>{children}</h1>
|
|
124
|
+
);
|
|
125
|
+
},
|
|
126
|
+
h2({ children }) {
|
|
127
|
+
return (
|
|
128
|
+
<h2 className={`${cls.heading} ${cls.heading}--2`}>{children}</h2>
|
|
129
|
+
);
|
|
130
|
+
},
|
|
131
|
+
h3({ children }) {
|
|
132
|
+
return (
|
|
133
|
+
<h3 className={`${cls.heading} ${cls.heading}--3`}>{children}</h3>
|
|
134
|
+
);
|
|
135
|
+
},
|
|
136
|
+
h4({ children }) {
|
|
137
|
+
return (
|
|
138
|
+
<h4 className={`${cls.heading} ${cls.heading}--4`}>{children}</h4>
|
|
139
|
+
);
|
|
140
|
+
},
|
|
141
|
+
h5({ children }) {
|
|
142
|
+
return (
|
|
143
|
+
<h5 className={`${cls.heading} ${cls.heading}--5`}>{children}</h5>
|
|
144
|
+
);
|
|
145
|
+
},
|
|
146
|
+
h6({ children }) {
|
|
147
|
+
return (
|
|
148
|
+
<h6 className={`${cls.heading} ${cls.heading}--6`}>{children}</h6>
|
|
149
|
+
);
|
|
150
|
+
},
|
|
151
|
+
ul({ children }) {
|
|
152
|
+
return <ul className={cls.ul}>{children}</ul>;
|
|
153
|
+
},
|
|
154
|
+
ol({ children }) {
|
|
155
|
+
return <ol className={cls.ol}>{children}</ol>;
|
|
156
|
+
},
|
|
157
|
+
li({ children }) {
|
|
158
|
+
return <li className={cls.li}>{children}</li>;
|
|
159
|
+
},
|
|
160
|
+
a({ href, children }) {
|
|
161
|
+
return (
|
|
162
|
+
<a
|
|
163
|
+
className={cls.link}
|
|
164
|
+
href={href}
|
|
165
|
+
target="_blank"
|
|
166
|
+
rel="noopener noreferrer"
|
|
167
|
+
>
|
|
168
|
+
{children}
|
|
169
|
+
</a>
|
|
170
|
+
);
|
|
171
|
+
},
|
|
172
|
+
blockquote({ children }) {
|
|
173
|
+
return <blockquote className={cls.blockquote}>{children}</blockquote>;
|
|
174
|
+
},
|
|
175
|
+
hr() {
|
|
176
|
+
return <hr className={cls.hr} />;
|
|
177
|
+
},
|
|
178
|
+
code({ className, children, ...rest }) {
|
|
179
|
+
// `react-markdown` calls this renderer for BOTH inline (`` `foo` ``)
|
|
180
|
+
// and fenced (```` ```lang … ``` ````) code. The fenced form gets a
|
|
181
|
+
// `language-<lang>` class from remark; inline code has no className.
|
|
182
|
+
const langMatch = /language-(\w+)/.exec(className ?? "");
|
|
183
|
+
const isFenced = langMatch !== null;
|
|
184
|
+
if (!isFenced) {
|
|
185
|
+
return (
|
|
186
|
+
<code className={cls.inlineCode} {...rest}>
|
|
187
|
+
{children}
|
|
188
|
+
</code>
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
// Fenced: keep `react-markdown`'s default `<pre><code class="language-…">`
|
|
192
|
+
// structure so future syntax-highlighter integrations (or wrapper
|
|
193
|
+
// overrides via `renderMessageBubble`) can target the language class.
|
|
194
|
+
return (
|
|
195
|
+
<code className={className} {...rest}>
|
|
196
|
+
{children}
|
|
197
|
+
</code>
|
|
198
|
+
);
|
|
199
|
+
},
|
|
200
|
+
pre({ children }) {
|
|
201
|
+
return <pre className={cls.codeBlock}>{children}</pre>;
|
|
202
|
+
},
|
|
203
|
+
// GFM tables. We wrap the table in a horizontally-scrollable div so
|
|
204
|
+
// wide tables (which Letta loves to produce when summarising data)
|
|
205
|
+
// don't push the chat bubble past its `max-width: 80%`.
|
|
206
|
+
table({ children }) {
|
|
207
|
+
return (
|
|
208
|
+
<div className={cls.tableWrapper}>
|
|
209
|
+
<table className={cls.table}>{children}</table>
|
|
210
|
+
</div>
|
|
211
|
+
);
|
|
212
|
+
},
|
|
213
|
+
thead({ children }) {
|
|
214
|
+
return <thead className={cls.thead}>{children}</thead>;
|
|
215
|
+
},
|
|
216
|
+
tbody({ children }) {
|
|
217
|
+
return <tbody className={cls.tbody}>{children}</tbody>;
|
|
218
|
+
},
|
|
219
|
+
tr({ children }) {
|
|
220
|
+
return <tr className={cls.tr}>{children}</tr>;
|
|
221
|
+
},
|
|
222
|
+
th({ children }) {
|
|
223
|
+
return <th className={cls.th}>{children}</th>;
|
|
224
|
+
},
|
|
225
|
+
td({ children }) {
|
|
226
|
+
return <td className={cls.td}>{children}</td>;
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Render markdown source as the body of an assistant message.
|
|
233
|
+
*
|
|
234
|
+
* @param props - see `MarkdownRendererProps`.
|
|
235
|
+
* @returns the rendered markdown tree, or `null` if `content` is
|
|
236
|
+
* whitespace-only.
|
|
237
|
+
*/
|
|
238
|
+
export function MarkdownRenderer(props: MarkdownRendererProps): ReactNode {
|
|
239
|
+
const trimmed = props.content.trim();
|
|
240
|
+
if (trimmed === "") return null;
|
|
241
|
+
const cls = { ...DEFAULT_CLASS_NAMES, ...(props.classNames ?? {}) };
|
|
242
|
+
const rootClass = props.className
|
|
243
|
+
? `${cls.root} ${props.className}`
|
|
244
|
+
: cls.root;
|
|
245
|
+
return (
|
|
246
|
+
<div className={rootClass} data-testid="markdown">
|
|
247
|
+
<ReactMarkdown
|
|
248
|
+
remarkPlugins={[remarkGfm, remarkMath]}
|
|
249
|
+
rehypePlugins={[rehypeKatex]}
|
|
250
|
+
components={buildComponents(cls)}
|
|
251
|
+
>
|
|
252
|
+
{trimmed}
|
|
253
|
+
</ReactMarkdown>
|
|
254
|
+
</div>
|
|
255
|
+
);
|
|
256
|
+
}
|