@mcp-b/react-components 0.14.2 → 0.16.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.
Files changed (251) hide show
  1. package/dist/AgentActivity-BNUNrP9O.d.ts +36 -0
  2. package/dist/{AgentChat-DQkqt82e.d.ts → AgentChat-CrlpbvQJ.d.ts} +58 -6
  3. package/dist/{CodeBlock-DUh9WOGo.d.ts → CodeBlock-BRajW4QU.d.ts} +1 -1
  4. package/dist/{CodeBlock-BUFXG8HW.js → CodeBlock-BmB4Xaqq.js} +15 -4
  5. package/dist/{FileTree-mpEIcfzA.js → FileTree-CkVbIMWV.js} +82 -89
  6. package/dist/Message-BkMdE3bS.js +375 -0
  7. package/dist/{ModelSelector-CPCpFAUt.js → ModelSelector-SlJNgwKY.js} +2 -2
  8. package/dist/{PromptInput-ClNqBiIw.d.ts → PromptInput-BWTuXMOD.d.ts} +123 -5
  9. package/dist/ResponsiveSidebarShell-Dd9DCcBT.d.ts +67 -0
  10. package/dist/{Select-Dl_vF_Bt.d.ts → Select-BeEsefzh.d.ts} +12 -2
  11. package/dist/{ThinkChat-BPcehdbP.js → ThinkChat-CzC-zNGA.js} +24 -36
  12. package/dist/{ThinkChatActivity-BmwuIigx.d.ts → ThinkChatActivity-BFQnb2ct.d.ts} +3 -10
  13. package/dist/ThinkChatActivitySummary-BPmu9a-c.d.ts +39 -0
  14. package/dist/{ThinkChatToolParts-CDEjqS6A.d.ts → ThinkChatToolParts-CSzVwMXf.d.ts} +13 -3
  15. package/dist/ThinkExecutionRun-ChhWhOoU.d.ts +30 -0
  16. package/dist/Toggle-CAAlNl-M.d.ts +69 -0
  17. package/dist/ToggleGroup-8hPv-b69.d.ts +73 -0
  18. package/dist/Workspace-D39LxGvP.d.ts +62 -0
  19. package/dist/WorkspaceFile-DOZkPwzu.d.ts +106 -0
  20. package/dist/WorkspaceFileView-rSN_yT0L.js +744 -0
  21. package/dist/WorkspaceLink-DIPbXrUM.js +337 -0
  22. package/dist/WorkspaceLink-DK1DWMHe.d.ts +89 -0
  23. package/dist/components/Activity.d.ts +27 -1
  24. package/dist/components/Activity.js +33 -15
  25. package/dist/components/AgentActivity.d.ts +2 -0
  26. package/dist/components/AgentActivity.js +45 -0
  27. package/dist/components/AgentActivityPreview.d.ts +46 -0
  28. package/dist/components/AgentActivityPreview.js +94 -0
  29. package/dist/components/AgentAttention.d.ts +73 -0
  30. package/dist/components/AgentAttention.js +85 -0
  31. package/dist/components/AgentChat.d.ts +2 -2
  32. package/dist/components/AgentChat.js +224 -200
  33. package/dist/components/AgentChatMessageEditor.d.ts +29 -0
  34. package/dist/components/AgentChatMessageEditor.js +92 -0
  35. package/dist/components/AgentChatTurnError.d.ts +17 -0
  36. package/dist/components/AgentChatTurnError.js +40 -0
  37. package/dist/components/AgentConnection.d.ts +12 -17
  38. package/dist/components/AgentConnection.js +99 -91
  39. package/dist/components/AppFrame.d.ts +24 -0
  40. package/dist/components/AppFrame.js +25 -0
  41. package/dist/components/AppTopBar.d.ts +71 -0
  42. package/dist/components/AppTopBar.js +82 -0
  43. package/dist/components/Artifact.js +1 -1
  44. package/dist/components/BrowserLiveView.js +1 -1
  45. package/dist/components/BrowserReplay.js +1 -1
  46. package/dist/components/BrowserRunPanel.js +1 -1
  47. package/dist/components/Card.d.ts +3 -0
  48. package/dist/components/Card.js +2 -1
  49. package/dist/components/ChainOfThought.d.ts +1 -1
  50. package/dist/components/ChainOfThought.js +1 -1
  51. package/dist/components/ChatGptSignInScreen.js +2 -2
  52. package/dist/components/Checkbox.js +5 -13
  53. package/dist/components/CheckboxGroup.d.ts +58 -2
  54. package/dist/components/CheckboxGroup.js +59 -1
  55. package/dist/components/CodeBlock.d.ts +1 -1
  56. package/dist/components/CodeBlock.js +1 -1
  57. package/dist/components/CodexModelSelector.js +1 -1
  58. package/dist/components/Commit.js +2 -2
  59. package/dist/components/ContextMenu.js +1 -1
  60. package/dist/components/Conversation.js +1 -1
  61. package/dist/components/DescriptionList.d.ts +12 -0
  62. package/dist/components/DescriptionList.js +11 -0
  63. package/dist/components/DescriptionListParts.d.ts +37 -0
  64. package/dist/components/DescriptionListParts.js +35 -0
  65. package/dist/components/EnvironmentVariables.js +2 -2
  66. package/dist/components/Fieldset.d.ts +13 -1
  67. package/dist/components/Fieldset.js +11 -2
  68. package/dist/components/FileTree.js +1 -1
  69. package/dist/components/IconButton.d.ts +33 -0
  70. package/dist/components/IconButton.js +27 -0
  71. package/dist/components/McpConnectionRequest.d.ts +44 -0
  72. package/dist/components/McpConnectionRequest.js +122 -0
  73. package/dist/components/McpServerPicker.d.ts +48 -23
  74. package/dist/components/McpServerPicker.js +238 -189
  75. package/dist/components/Menubar.js +1 -1
  76. package/dist/components/Message.d.ts +1 -0
  77. package/dist/components/Message.js +1 -285
  78. package/dist/components/MessageScroller.js +1 -1
  79. package/dist/components/ModelSelector.js +1 -1
  80. package/dist/components/Pricing.d.ts +37 -0
  81. package/dist/components/Pricing.js +17 -0
  82. package/dist/components/PricingBillingToggle.d.ts +23 -0
  83. package/dist/components/PricingBillingToggle.js +86 -0
  84. package/dist/components/PricingConfirmationDialog.d.ts +25 -0
  85. package/dist/components/PricingConfirmationDialog.js +57 -0
  86. package/dist/components/PricingFAQ.d.ts +18 -0
  87. package/dist/components/PricingFAQ.js +27 -0
  88. package/dist/components/PricingPage.d.ts +2 -38
  89. package/dist/components/PricingPage.js +39 -359
  90. package/dist/components/PricingPlanCard.d.ts +22 -0
  91. package/dist/components/PricingPlanCard.js +109 -0
  92. package/dist/components/PricingUsageCalculator.d.ts +22 -0
  93. package/dist/components/PricingUsageCalculator.js +96 -0
  94. package/dist/components/PromptInput.d.ts +2 -2
  95. package/dist/components/PromptInput.js +210 -15
  96. package/dist/components/Queue.js +1 -1
  97. package/dist/components/Reasoning.d.ts +2 -1
  98. package/dist/components/Reasoning.js +14 -29
  99. package/dist/components/ResizableSidePanel.d.ts +57 -0
  100. package/dist/components/ResizableSidePanel.js +151 -0
  101. package/dist/components/ResponsiveSidebarShell.d.ts +2 -0
  102. package/dist/components/ResponsiveSidebarShell.js +129 -0
  103. package/dist/components/Select.d.ts +2 -2
  104. package/dist/components/Select.js +11 -2
  105. package/dist/components/Slider.d.ts +13 -1
  106. package/dist/components/Slider.js +11 -0
  107. package/dist/components/Sources.js +1 -1
  108. package/dist/components/Stepper.d.ts +4 -0
  109. package/dist/components/Stepper.js +5 -3
  110. package/dist/components/SubagentRun.d.ts +18 -19
  111. package/dist/components/SubagentRun.js +25 -18
  112. package/dist/components/SubagentRunIndicator.d.ts +22 -0
  113. package/dist/components/SubagentRunIndicator.js +33 -0
  114. package/dist/components/SubagentRunList.d.ts +25 -0
  115. package/dist/components/SubagentRunList.js +26 -0
  116. package/dist/components/SubagentRunSelector.d.ts +47 -0
  117. package/dist/components/SubagentRunSelector.js +55 -0
  118. package/dist/components/Task.js +1 -1
  119. package/dist/components/Terminal.js +2 -2
  120. package/dist/components/TestResults.js +1 -1
  121. package/dist/components/Textarea.d.ts +21 -0
  122. package/dist/components/Textarea.js +19 -0
  123. package/dist/components/ThemeModeControl.d.ts +24 -0
  124. package/dist/components/ThemeModeControl.js +52 -0
  125. package/dist/components/ThemeProvider.d.ts +38 -0
  126. package/dist/components/ThemeProvider.js +80 -0
  127. package/dist/components/ThinkChat.d.ts +29 -6
  128. package/dist/components/ThinkChat.js +7 -4
  129. package/dist/components/ThinkChatActivity.d.ts +3 -2
  130. package/dist/components/ThinkChatActivity.js +12 -318
  131. package/dist/components/ThinkChatActivitySummary.d.ts +2 -0
  132. package/dist/components/ThinkChatActivitySummary.js +421 -0
  133. package/dist/components/ThinkChatToolPanels.d.ts +7 -5
  134. package/dist/components/ThinkChatToolPanels.js +70 -8
  135. package/dist/components/ThinkChatToolParts.d.ts +2 -2
  136. package/dist/components/ThinkChatToolParts.js +36 -10
  137. package/dist/components/ThinkExecutionDetail.d.ts +20 -0
  138. package/dist/components/ThinkExecutionDetail.js +80 -0
  139. package/dist/components/ThinkExecutionRun.d.ts +2 -0
  140. package/dist/components/ThinkExecutionRun.js +72 -0
  141. package/dist/components/ThinkExecutionStatus.d.ts +22 -0
  142. package/dist/components/ThinkExecutionStatus.js +36 -0
  143. package/dist/components/ThinkExecutionWorkbench.d.ts +7 -0
  144. package/dist/components/ThinkExecutionWorkbench.js +69 -225
  145. package/dist/components/ThinkFullApp.d.ts +58 -14
  146. package/dist/components/ThinkFullApp.js +154 -160
  147. package/dist/components/ThinkFullAppViewSwitch.d.ts +31 -0
  148. package/dist/components/ThinkFullAppViewSwitch.js +34 -0
  149. package/dist/components/ThinkRoutine.d.ts +36 -0
  150. package/dist/components/ThinkRoutine.js +15 -0
  151. package/dist/components/ThinkRoutineBrowser.d.ts +25 -0
  152. package/dist/components/ThinkRoutineBrowser.js +156 -0
  153. package/dist/components/ThinkRoutineDetail.d.ts +24 -0
  154. package/dist/components/ThinkRoutineDetail.js +102 -0
  155. package/dist/components/ThinkRoutineForm.d.ts +32 -0
  156. package/dist/components/ThinkRoutineForm.js +151 -0
  157. package/dist/components/ThinkRoutineLibrary.d.ts +74 -0
  158. package/dist/components/ThinkRoutineLibrary.js +178 -0
  159. package/dist/components/ThinkRoutineRuns.d.ts +24 -0
  160. package/dist/components/ThinkRoutineRuns.js +68 -0
  161. package/dist/components/ThinkThreadPicker.d.ts +18 -1
  162. package/dist/components/ThinkThreadPicker.js +51 -5
  163. package/dist/components/ThinkThreadShell.d.ts +12 -9
  164. package/dist/components/ThinkThreadShell.js +17 -137
  165. package/dist/components/Toggle.d.ts +1 -68
  166. package/dist/components/ToggleGroup.d.ts +1 -72
  167. package/dist/components/Tooltip.d.ts +3 -1
  168. package/dist/components/Tooltip.js +4 -2
  169. package/dist/components/WebPreview.js +1 -1
  170. package/dist/components/Workspace.d.ts +2 -0
  171. package/dist/components/Workspace.js +424 -0
  172. package/dist/components/WorkspaceBrowser.d.ts +32 -0
  173. package/dist/components/WorkspaceBrowser.js +103 -0
  174. package/dist/components/WorkspaceExplorer.d.ts +12 -79
  175. package/dist/components/WorkspaceExplorer.js +116 -330
  176. package/dist/components/WorkspaceFile.d.ts +2 -0
  177. package/dist/components/WorkspaceFile.js +195 -0
  178. package/dist/components/WorkspaceFileView.d.ts +26 -0
  179. package/dist/components/WorkspaceFileView.js +2 -0
  180. package/dist/components/WorkspaceHeader.d.ts +35 -0
  181. package/dist/components/WorkspaceHeader.js +51 -0
  182. package/dist/components/WorkspaceLink.d.ts +2 -0
  183. package/dist/components/WorkspaceLink.js +2 -0
  184. package/dist/components/icons.d.ts +2 -2
  185. package/dist/components/icons.js +2 -2
  186. package/dist/{copy-button-DUMLYdsk.js → copy-button-Dejn5heL.js} +1 -1
  187. package/dist/icons-CpfUer49.js +85 -0
  188. package/dist/{icons-CUCz_Sft.d.ts → icons-GQd1xF4e.d.ts} +51 -1
  189. package/dist/styles/activity-header.css +75 -0
  190. package/dist/styles/activity.css +49 -63
  191. package/dist/styles/agent-activity-preview-overlay.css +80 -0
  192. package/dist/styles/agent-activity-preview.css +233 -0
  193. package/dist/styles/agent-attention.css +128 -0
  194. package/dist/styles/agent-chat.css +133 -4
  195. package/dist/styles/agent-connection.css +9 -9
  196. package/dist/styles/alert-dialog.css +11 -11
  197. package/dist/styles/app-frame.css +15 -0
  198. package/dist/styles/app-top-bar.css +102 -0
  199. package/dist/styles/avatar.css +0 -1
  200. package/dist/styles/browser-control-overlay.css +184 -0
  201. package/dist/styles/card.css +29 -8
  202. package/dist/styles/chain-of-thought.css +5 -5
  203. package/dist/styles/checkbox-group.css +69 -0
  204. package/dist/styles/codex-model-selector.css +3 -3
  205. package/dist/styles/combobox.css +2 -1
  206. package/dist/styles/context-menu.css +1 -1
  207. package/dist/styles/description-list.css +50 -0
  208. package/dist/styles/dialog.css +11 -11
  209. package/dist/styles/field.css +14 -14
  210. package/dist/styles/fieldset.css +15 -4
  211. package/dist/styles/index.css +14 -2
  212. package/dist/styles/mcp-connection-request.css +60 -0
  213. package/dist/styles/mcp-server-picker.css +96 -68
  214. package/dist/styles/menu.css +1 -1
  215. package/dist/styles/message.css +4 -43
  216. package/dist/styles/model-selector.css +18 -12
  217. package/dist/styles/popover.css +9 -9
  218. package/dist/styles/preview-card.css +1 -1
  219. package/dist/styles/pricing-page.css +21 -27
  220. package/dist/styles/prompt-input.css +225 -32
  221. package/dist/styles/reasoning.css +1 -55
  222. package/dist/styles/recipes.css +50 -24
  223. package/dist/styles/resizable-side-panel.css +66 -0
  224. package/dist/styles/responsive-sidebar-shell.css +169 -0
  225. package/dist/styles/select.css +13 -3
  226. package/dist/styles/sources.css +6 -6
  227. package/dist/styles/stepper.css +13 -0
  228. package/dist/styles/streamdown.css +0 -4
  229. package/dist/styles/subagent-run.css +59 -42
  230. package/dist/styles/task.css +17 -10
  231. package/dist/styles/test-results.css +17 -10
  232. package/dist/styles/textarea.css +20 -0
  233. package/dist/styles/theme-mode-control.css +72 -0
  234. package/dist/styles/think-execution-status.css +49 -0
  235. package/dist/styles/think-execution-workbench.css +16 -80
  236. package/dist/styles/think-full-app.css +143 -128
  237. package/dist/styles/think-routine-library.css +491 -0
  238. package/dist/styles/think-thread-picker.css +47 -3
  239. package/dist/styles/toast.css +6 -6
  240. package/dist/styles/toggle-group.css +7 -0
  241. package/dist/styles/tooltip.css +1 -1
  242. package/dist/styles/workspace-explorer.css +516 -64
  243. package/dist/utils/mcp-server-catalog.d.ts +82 -78
  244. package/dist/utils/mcp-server-catalog.js +64 -41
  245. package/dist/utils/structured-code.d.ts +1 -1
  246. package/dist/utils/theme.d.ts +22 -0
  247. package/dist/utils/theme.js +55 -0
  248. package/package.json +34 -28
  249. package/dist/icons-Ba9THQKz.js +0 -64
  250. package/dist/styles/think-resize-handle.css +0 -33
  251. package/dist/styles/think-thread-shell.css +0 -219
@@ -1,73 +1,2 @@
1
- import { ToggleVariantsOptions } from "./Toggle.js";
2
- import * as React from "react";
3
- import { ToggleGroup as ToggleGroup$1 } from "@base-ui/react/toggle-group";
4
- import { Toggle } from "@base-ui/react/toggle";
5
-
6
- //#region src/components/ToggleGroup.d.ts
7
- type ToggleGroupSize = ToggleVariantsOptions["size"] | "md";
8
- interface ToggleGroupProps extends Omit<React.ComponentPropsWithRef<typeof ToggleGroup$1>, "className"> {
9
- className?: string;
10
- variant?: ToggleVariantsOptions["variant"];
11
- /**
12
- * The size of the toggle group.
13
- * @default 'md'
14
- */
15
- size?: ToggleGroupSize;
16
- spacing?: number;
17
- }
18
- interface ToggleGroupItemProps extends Omit<React.ComponentPropsWithRef<typeof Toggle>, "className">, ToggleVariantsOptions {}
19
- /**
20
- * A toggle group component for selecting one or multiple options.
21
- *
22
- * @example
23
- * ```tsx
24
- * // Single selection (defaultValue is an array)
25
- * <ToggleGroup defaultValue={["center"]}>
26
- * <ToggleGroupItem value="left">Left</ToggleGroupItem>
27
- * <ToggleGroupItem value="center">Center</ToggleGroupItem>
28
- * <ToggleGroupItem value="right">Right</ToggleGroupItem>
29
- * </ToggleGroup>
30
- * ```
31
- *
32
- * @example
33
- * ```tsx
34
- * // Multiple selection
35
- * <ToggleGroup multiple defaultValue={["bold", "italic"]}>
36
- * <ToggleGroupItem value="bold">Bold</ToggleGroupItem>
37
- * <ToggleGroupItem value="italic">Italic</ToggleGroupItem>
38
- * <ToggleGroupItem value="underline">Underline</ToggleGroupItem>
39
- * </ToggleGroup>
40
- * ```
41
- *
42
- * @see {@link https://base-ui.com/react/components/toggle-group | Base UI Toggle Group}
43
- */
44
- declare function ToggleGroupRoot({
45
- size,
46
- spacing,
47
- variant,
48
- className,
49
- children,
50
- style,
51
- ref,
52
- ...props
53
- }: ToggleGroupProps & {
54
- ref?: React.Ref<HTMLDivElement>;
55
- }): React.JSX.Element;
56
- /**
57
- * A single toggle item within a ToggleGroup.
58
- */
59
- declare function ToggleGroupItem({
60
- className,
61
- variant,
62
- size,
63
- ref,
64
- ...props
65
- }: ToggleGroupItemProps & {
66
- ref?: React.Ref<HTMLButtonElement>;
67
- }): React.JSX.Element;
68
- declare const ToggleGroup: {
69
- Root: typeof ToggleGroupRoot;
70
- Item: typeof ToggleGroupItem;
71
- };
72
- //#endregion
1
+ import { n as ToggleGroupItemProps, r as ToggleGroupProps, t as ToggleGroup } from "../ToggleGroup-8hPv-b69.js";
73
2
  export { ToggleGroup, ToggleGroupItemProps, ToggleGroupProps };
@@ -49,6 +49,7 @@ declare function TooltipTrigger(props: TooltipTriggerProps): React.JSX.Element;
49
49
  declare function TooltipPopup({
50
50
  className,
51
51
  ref,
52
+ role,
52
53
  ...props
53
54
  }: TooltipPopupProps & {
54
55
  ref?: React.Ref<HTMLDivElement>;
@@ -73,7 +74,8 @@ declare function TooltipArrow({
73
74
  ref?: React.Ref<HTMLDivElement>;
74
75
  }): React.JSX.Element;
75
76
  /**
76
- * An accessible tooltip assembled from explicit Base UI parts.
77
+ * An accessible tooltip assembled from explicit Base UI parts. Popup defaults
78
+ * to `role="tooltip"` so assistive technology can identify revealed help text.
77
79
  */
78
80
  declare const Tooltip: {
79
81
  createHandle: typeof Tooltip$1.createHandle;
@@ -36,7 +36,7 @@ function TooltipTrigger(props) {
36
36
  ...props
37
37
  });
38
38
  }
39
- function TooltipPopup({ className = "", ref, ...props }) {
39
+ function TooltipPopup({ className = "", ref, role = "tooltip", ...props }) {
40
40
  const classes = [
41
41
  "tooltip__popup",
42
42
  "base-ui-popup",
@@ -44,6 +44,7 @@ function TooltipPopup({ className = "", ref, ...props }) {
44
44
  ].filter(Boolean).join(" ");
45
45
  return /* @__PURE__ */ jsx(Tooltip$1.Popup, {
46
46
  ref,
47
+ role,
47
48
  "data-slot": "tooltip-content",
48
49
  className: classes,
49
50
  ...props
@@ -73,7 +74,8 @@ function TooltipArrow({ className = "", ref, ...props }) {
73
74
  });
74
75
  }
75
76
  /**
76
- * An accessible tooltip assembled from explicit Base UI parts.
77
+ * An accessible tooltip assembled from explicit Base UI parts. Popup defaults
78
+ * to `role="tooltip"` so assistive technology can identify revealed help text.
77
79
  */
78
80
  const Tooltip = {
79
81
  createHandle: Tooltip$1.createHandle,
@@ -1,5 +1,5 @@
1
1
  import { t as cx } from "../class-names-9UtZwb0J.js";
2
- import { A as RefreshIcon, n as ArrowLeftIcon, o as ChevronDownIcon, r as ArrowRightIcon } from "../icons-Ba9THQKz.js";
2
+ import { L as RefreshIcon, n as ArrowLeftIcon, r as ArrowRightIcon, s as ChevronDownIcon } from "../icons-CpfUer49.js";
3
3
  import { Button } from "./Button.js";
4
4
  import { Tooltip } from "./Tooltip.js";
5
5
  import { Badge } from "./Badge.js";
@@ -0,0 +1,2 @@
1
+ import { a as useWorkspace, i as WorkspaceState, n as WorkspaceInfo, r as WorkspaceSource, t as UseWorkspaceOptions } from "../Workspace-D39LxGvP.js";
2
+ export { UseWorkspaceOptions, WorkspaceInfo, WorkspaceSource, WorkspaceState, useWorkspace };
@@ -0,0 +1,424 @@
1
+ import { getWorkspaceBasename, inferWorkspaceMedia } from "./WorkspaceFile.js";
2
+ import * as React from "react";
3
+ //#region src/components/Workspace.ts
4
+ const DEFAULT_MAX_INLINE_ASSET_BYTES = 32 * 1024 * 1024;
5
+ const WORKSPACE_DIRECTORY_PAGE_SIZE = 1e3;
6
+ const EMPTY_ENTRIES_BY_DIRECTORY = Object.freeze({});
7
+ const EMPTY_ENTRY_BY_PATH = /* @__PURE__ */ new Map();
8
+ const EMPTY_PATHS = /* @__PURE__ */ new Set();
9
+ function toErrorMessage(error) {
10
+ return error instanceof Error ? error.message : String(error);
11
+ }
12
+ function normalizeWorkspacePath(path) {
13
+ if (!path.startsWith("/") || path.includes("\0")) return null;
14
+ const segments = [];
15
+ for (const segment of path.split("/")) {
16
+ if (!segment || segment === ".") continue;
17
+ if (segment === "..") segments.pop();
18
+ else segments.push(segment);
19
+ }
20
+ return `/${segments.join("/")}`;
21
+ }
22
+ function isPathWithinWorkspaceRoot(path, root) {
23
+ const normalizedPath = normalizeWorkspacePath(path);
24
+ const normalizedRoot = normalizeWorkspacePath(root);
25
+ if (!normalizedPath || !normalizedRoot) return false;
26
+ return normalizedRoot === "/" || normalizedPath === normalizedRoot || normalizedPath.startsWith(`${normalizedRoot}/`);
27
+ }
28
+ function getWorkspaceParentPath(path) {
29
+ const separatorIndex = path.lastIndexOf("/");
30
+ return separatorIndex <= 0 ? "/" : path.slice(0, separatorIndex);
31
+ }
32
+ function getAssetDataSize(asset) {
33
+ if (asset.kind === "url") return void 0;
34
+ if (asset.data instanceof ArrayBuffer || asset.data instanceof Uint8Array) return asset.data.byteLength;
35
+ return asset.data.size;
36
+ }
37
+ function normalizeWorkspaceAsset(asset, path, inferredMedia, info) {
38
+ const media = asset.mimeType?.trim() ? inferWorkspaceMedia(path, asset.mimeType) : inferredMedia;
39
+ if (!media) return null;
40
+ const metadata = {
41
+ mimeType: media.mimeType,
42
+ size: asset.size ?? getAssetDataSize(asset) ?? info.size
43
+ };
44
+ return {
45
+ asset: asset.kind === "url" ? {
46
+ ...asset,
47
+ ...metadata
48
+ } : {
49
+ ...asset,
50
+ ...metadata
51
+ },
52
+ media: inferWorkspaceMedia(path, media.mimeType) ?? media
53
+ };
54
+ }
55
+ async function readWorkspaceAssetBytes(source, path, info, maxInlineAssetBytes) {
56
+ if (info.size > maxInlineAssetBytes) {
57
+ const maximumMiB = Math.floor(maxInlineAssetBytes / (1024 * 1024));
58
+ throw new Error(`This file is too large for the built-in byte preview (${maximumMiB.toLocaleString()} MiB maximum). Provide resolveFileAsset with a URL instead.`);
59
+ }
60
+ const data = await source.readFileBytes(path);
61
+ if (data && data.byteLength > maxInlineAssetBytes) throw new Error("The returned bytes exceed the built-in preview limit. Provide resolveFileAsset with a URL instead.");
62
+ return data ? {
63
+ kind: "data",
64
+ data
65
+ } : null;
66
+ }
67
+ /**
68
+ * Headless state for browsing a Think workspace: lazy directory loading,
69
+ * cached file reads, expansion/selection, and refresh. Feed the result to
70
+ * `WorkspaceExplorer`, or compose `WorkspaceBrowser` and `WorkspaceFileView`.
71
+ */
72
+ function useWorkspace({ source, root = "/", resolveFileAsset, maxInlineAssetBytes = DEFAULT_MAX_INLINE_ASSET_BYTES }) {
73
+ const [entriesByDirectory, setEntriesByDirectory] = React.useState({});
74
+ const [filesByPath, setFilesByPath] = React.useState({});
75
+ const [expandedPaths, setExpandedPathsState] = React.useState(/* @__PURE__ */ new Set());
76
+ const [selectedPath, setSelectedPath] = React.useState(null);
77
+ const [isLoading, setIsLoading] = React.useState(false);
78
+ const [loadingPaths, setLoadingPaths] = React.useState(/* @__PURE__ */ new Set());
79
+ const [directoryErrorsByPath, setDirectoryErrorsByPath] = React.useState({});
80
+ const [info, setInfo] = React.useState(null);
81
+ const [activeAssetFile, setActiveAssetFile] = React.useState(null);
82
+ const [stateGeneration, setStateGeneration] = React.useState(0);
83
+ const loadedDirectoriesRef = React.useRef(/* @__PURE__ */ new Set());
84
+ const directoryRequestVersionsRef = React.useRef(/* @__PURE__ */ new Map());
85
+ const nextDirectoryRequestVersionRef = React.useRef(0);
86
+ const nextInfoRequestVersionRef = React.useRef(0);
87
+ const refreshRequestVersionRef = React.useRef(0);
88
+ const loadingOperationVersionRef = React.useRef(0);
89
+ const selectedPathRef = React.useRef(null);
90
+ const fileRequestRef = React.useRef(null);
91
+ const resolveFileAssetRef = React.useRef(resolveFileAsset);
92
+ resolveFileAssetRef.current = resolveFileAsset;
93
+ const maxInlineAssetBytesRef = React.useRef(DEFAULT_MAX_INLINE_ASSET_BYTES);
94
+ maxInlineAssetBytesRef.current = Number.isFinite(maxInlineAssetBytes) && maxInlineAssetBytes >= 0 ? maxInlineAssetBytes : DEFAULT_MAX_INLINE_ASSET_BYTES;
95
+ const sourceIdentityRef = React.useRef({
96
+ source,
97
+ root,
98
+ generation: 0
99
+ });
100
+ if (sourceIdentityRef.current.source !== source || sourceIdentityRef.current.root !== root) sourceIdentityRef.current = {
101
+ source,
102
+ root,
103
+ generation: sourceIdentityRef.current.generation + 1
104
+ };
105
+ const entryByPath = React.useMemo(() => {
106
+ const map = /* @__PURE__ */ new Map();
107
+ for (const entries of Object.values(entriesByDirectory)) for (const entry of entries) map.set(entry.path, entry);
108
+ return map;
109
+ }, [entriesByDirectory]);
110
+ const markLoading = React.useCallback((path, loading) => {
111
+ setLoadingPaths((current) => {
112
+ const next = new Set(current);
113
+ if (loading) next.add(path);
114
+ else next.delete(path);
115
+ return next;
116
+ });
117
+ }, []);
118
+ const setDirectoryError = React.useCallback((path, message) => {
119
+ setDirectoryErrorsByPath((current) => {
120
+ if (message !== null) {
121
+ if (current[path] === message) return current;
122
+ return {
123
+ ...current,
124
+ [path]: message
125
+ };
126
+ }
127
+ if (!Object.hasOwn(current, path)) return current;
128
+ const next = { ...current };
129
+ delete next[path];
130
+ return next;
131
+ });
132
+ }, []);
133
+ const activateAssetFile = React.useCallback((file) => {
134
+ setFilesByPath((current) => {
135
+ if (!Object.hasOwn(current, file.path)) return current;
136
+ const next = { ...current };
137
+ delete next[file.path];
138
+ return next;
139
+ });
140
+ setActiveAssetFile(file);
141
+ }, []);
142
+ const cacheTextFile = React.useCallback((file) => {
143
+ setActiveAssetFile((current) => current?.path === file.path ? null : current);
144
+ setFilesByPath((current) => ({
145
+ ...current,
146
+ [file.path]: file
147
+ }));
148
+ }, []);
149
+ const cancelFileLoad = React.useCallback(() => {
150
+ const request = fileRequestRef.current;
151
+ if (!request) return;
152
+ request.controller.abort();
153
+ fileRequestRef.current = null;
154
+ markLoading(request.path, false);
155
+ }, [markLoading]);
156
+ const loadDirectory = React.useCallback(async (path, { force = false } = {}) => {
157
+ if (!force && loadedDirectoriesRef.current.has(path)) return;
158
+ const identity = sourceIdentityRef.current;
159
+ if (identity.source !== source || identity.root !== root) return;
160
+ const generation = identity.generation;
161
+ const requestVersion = nextDirectoryRequestVersionRef.current + 1;
162
+ nextDirectoryRequestVersionRef.current = requestVersion;
163
+ directoryRequestVersionsRef.current.set(path, requestVersion);
164
+ const requestIsCurrent = () => generation === sourceIdentityRef.current.generation && directoryRequestVersionsRef.current.get(path) === requestVersion;
165
+ markLoading(path, true);
166
+ try {
167
+ const entries = [];
168
+ let offset = 0;
169
+ for (;;) {
170
+ const page = await source.readDir(path, {
171
+ limit: WORKSPACE_DIRECTORY_PAGE_SIZE,
172
+ offset
173
+ });
174
+ if (!requestIsCurrent()) return;
175
+ entries.push(...page);
176
+ if (page.length < WORKSPACE_DIRECTORY_PAGE_SIZE) break;
177
+ offset += page.length;
178
+ }
179
+ loadedDirectoriesRef.current.add(path);
180
+ setEntriesByDirectory((current) => ({
181
+ ...current,
182
+ [path]: entries
183
+ }));
184
+ setDirectoryError(path, null);
185
+ return entries;
186
+ } catch (listError) {
187
+ if (!requestIsCurrent()) return;
188
+ setDirectoryError(path, toErrorMessage(listError));
189
+ return null;
190
+ } finally {
191
+ if (requestIsCurrent()) markLoading(path, false);
192
+ }
193
+ }, [
194
+ source,
195
+ root,
196
+ markLoading,
197
+ setDirectoryError
198
+ ]);
199
+ const loadFile = React.useCallback(async (path, { force = false, refreshRequestVersion } = {}) => {
200
+ const listedFileInfo = entryByPath.get(path) ?? null;
201
+ const cachedFile = filesByPath[path];
202
+ if (!force && cachedFile && !inferWorkspaceMedia(path, listedFileInfo?.mimeType)) return;
203
+ const identity = sourceIdentityRef.current;
204
+ if (identity.source !== source || identity.root !== root) return;
205
+ const generation = identity.generation;
206
+ cancelFileLoad();
207
+ const controller = new AbortController();
208
+ const request = {
209
+ path,
210
+ controller
211
+ };
212
+ fileRequestRef.current = request;
213
+ markLoading(path, true);
214
+ let fileInfo = listedFileInfo;
215
+ let media = inferWorkspaceMedia(path, fileInfo?.mimeType);
216
+ const requestIsCurrent = () => !controller.signal.aborted && generation === sourceIdentityRef.current.generation && selectedPathRef.current === path && (refreshRequestVersion === void 0 || refreshRequestVersionRef.current === refreshRequestVersion);
217
+ try {
218
+ if (!isPathWithinWorkspaceRoot(path, root)) throw new Error("This file is outside the configured workspace root.");
219
+ const resolvedInfo = await source.stat(path);
220
+ if (!requestIsCurrent()) return;
221
+ if (!resolvedInfo) {
222
+ fileInfo = null;
223
+ throw new Error("File metadata is unavailable because source.stat() returned null.");
224
+ }
225
+ fileInfo = resolvedInfo;
226
+ const readPath = normalizeWorkspacePath(resolvedInfo.path);
227
+ if (!readPath) throw new Error("The workspace source returned an invalid file path from stat().");
228
+ if (readPath !== resolvedInfo.path) throw new Error("The workspace source returned a non-canonical file path from stat().");
229
+ if (!isPathWithinWorkspaceRoot(readPath, root)) throw new Error("This file's resolved path is outside the configured workspace root.");
230
+ media = inferWorkspaceMedia(readPath, resolvedInfo.mimeType);
231
+ const resolver = resolveFileAssetRef.current;
232
+ const resolvedAsset = resolver ? await resolver({
233
+ path: readPath,
234
+ requestedPath: path,
235
+ root: normalizeWorkspacePath(root) ?? root,
236
+ info: resolvedInfo,
237
+ signal: controller.signal
238
+ }) : null;
239
+ if (!requestIsCurrent()) return;
240
+ if (resolvedAsset) {
241
+ const normalized = normalizeWorkspaceAsset(resolvedAsset, readPath, media, resolvedInfo);
242
+ if (!normalized) throw new Error("The host returned an asset without a supported image, PDF, audio, or video MIME type.");
243
+ media = normalized.media;
244
+ activateAssetFile({
245
+ path,
246
+ name: getWorkspaceBasename(path),
247
+ content: null,
248
+ asset: normalized.asset,
249
+ info: resolvedInfo,
250
+ error: null
251
+ });
252
+ return;
253
+ }
254
+ if (media) {
255
+ const byteAsset = await readWorkspaceAssetBytes(source, readPath, resolvedInfo, maxInlineAssetBytesRef.current);
256
+ if (!requestIsCurrent()) return;
257
+ const normalized = byteAsset ? normalizeWorkspaceAsset(byteAsset, readPath, media, resolvedInfo) : null;
258
+ activateAssetFile({
259
+ path,
260
+ name: getWorkspaceBasename(path),
261
+ content: null,
262
+ asset: normalized?.asset ?? null,
263
+ info: resolvedInfo,
264
+ error: null
265
+ });
266
+ return;
267
+ }
268
+ const content = await source.readFile(readPath);
269
+ if (!requestIsCurrent()) return;
270
+ cacheTextFile({
271
+ path,
272
+ name: getWorkspaceBasename(path),
273
+ content,
274
+ asset: null,
275
+ info: resolvedInfo,
276
+ error: null
277
+ });
278
+ } catch (readError) {
279
+ if (!requestIsCurrent()) return;
280
+ const failedFile = {
281
+ path,
282
+ name: getWorkspaceBasename(path),
283
+ content: null,
284
+ asset: null,
285
+ info: fileInfo,
286
+ error: toErrorMessage(readError)
287
+ };
288
+ if (media) activateAssetFile(failedFile);
289
+ else cacheTextFile(failedFile);
290
+ } finally {
291
+ if (fileRequestRef.current === request && generation === sourceIdentityRef.current.generation) {
292
+ fileRequestRef.current = null;
293
+ markLoading(path, false);
294
+ }
295
+ }
296
+ }, [
297
+ activateAssetFile,
298
+ cacheTextFile,
299
+ cancelFileLoad,
300
+ entryByPath,
301
+ filesByPath,
302
+ markLoading,
303
+ root,
304
+ source
305
+ ]);
306
+ const loadInfo = React.useCallback(async () => {
307
+ if (!("getWorkspaceInfo" in source)) return;
308
+ if (typeof source.getWorkspaceInfo !== "function") return;
309
+ const identity = sourceIdentityRef.current;
310
+ if (identity.source !== source || identity.root !== root) return;
311
+ const generation = identity.generation;
312
+ const requestVersion = nextInfoRequestVersionRef.current + 1;
313
+ nextInfoRequestVersionRef.current = requestVersion;
314
+ const requestIsCurrent = () => generation === sourceIdentityRef.current.generation && nextInfoRequestVersionRef.current === requestVersion;
315
+ try {
316
+ const nextInfo = await source.getWorkspaceInfo();
317
+ if (requestIsCurrent()) setInfo(nextInfo);
318
+ } catch {
319
+ if (requestIsCurrent()) setInfo(null);
320
+ }
321
+ }, [source, root]);
322
+ React.useEffect(() => {
323
+ const generation = sourceIdentityRef.current.generation;
324
+ const loadingOperationVersion = loadingOperationVersionRef.current + 1;
325
+ loadingOperationVersionRef.current = loadingOperationVersion;
326
+ refreshRequestVersionRef.current += 1;
327
+ cancelFileLoad();
328
+ setEntriesByDirectory({});
329
+ setFilesByPath({});
330
+ setActiveAssetFile(null);
331
+ setExpandedPathsState(/* @__PURE__ */ new Set());
332
+ setSelectedPath(null);
333
+ selectedPathRef.current = null;
334
+ setLoadingPaths(/* @__PURE__ */ new Set());
335
+ setDirectoryErrorsByPath({});
336
+ setInfo(null);
337
+ setStateGeneration(generation);
338
+ loadedDirectoriesRef.current = /* @__PURE__ */ new Set();
339
+ directoryRequestVersionsRef.current = /* @__PURE__ */ new Map();
340
+ setIsLoading(true);
341
+ Promise.all([loadDirectory(root, { force: true }), loadInfo()]).finally(() => {
342
+ if (generation === sourceIdentityRef.current.generation && loadingOperationVersionRef.current === loadingOperationVersion) setIsLoading(false);
343
+ });
344
+ }, [
345
+ cancelFileLoad,
346
+ loadDirectory,
347
+ loadInfo,
348
+ root
349
+ ]);
350
+ React.useEffect(() => () => {
351
+ fileRequestRef.current?.controller.abort();
352
+ }, []);
353
+ const setExpandedPaths = React.useCallback((next) => {
354
+ setExpandedPathsState((current) => {
355
+ for (const path of next) if (!current.has(path)) loadDirectory(path);
356
+ return next;
357
+ });
358
+ }, [loadDirectory]);
359
+ const selectFile = React.useCallback((path) => {
360
+ cancelFileLoad();
361
+ selectedPathRef.current = path;
362
+ setActiveAssetFile(null);
363
+ setSelectedPath(path);
364
+ if (path !== null) loadFile(path);
365
+ }, [cancelFileLoad, loadFile]);
366
+ const refresh = React.useCallback(() => {
367
+ (async () => {
368
+ const identity = sourceIdentityRef.current;
369
+ if (identity.source !== source || identity.root !== root) return;
370
+ const generation = identity.generation;
371
+ const refreshRequestVersion = refreshRequestVersionRef.current + 1;
372
+ refreshRequestVersionRef.current = refreshRequestVersion;
373
+ const loadingOperationVersion = loadingOperationVersionRef.current + 1;
374
+ loadingOperationVersionRef.current = loadingOperationVersion;
375
+ const requestIsCurrent = () => generation === sourceIdentityRef.current.generation && refreshRequestVersionRef.current === refreshRequestVersion;
376
+ setIsLoading(true);
377
+ try {
378
+ const directoryPaths = [.../* @__PURE__ */ new Set([root, ...expandedPaths])];
379
+ const [refreshedListings] = await Promise.all([Promise.all(directoryPaths.map((path) => loadDirectory(path, { force: true }))), loadInfo()]);
380
+ if (!requestIsCurrent()) return;
381
+ const refreshedSelectedPath = selectedPathRef.current;
382
+ if (refreshedSelectedPath) {
383
+ const selectedDirectoryIndex = directoryPaths.indexOf(getWorkspaceParentPath(refreshedSelectedPath));
384
+ const selectedDirectoryListing = refreshedListings[selectedDirectoryIndex];
385
+ if (selectedDirectoryIndex >= 0 && (selectedDirectoryListing === null || selectedDirectoryListing === void 0)) return;
386
+ await loadFile(refreshedSelectedPath, {
387
+ force: true,
388
+ refreshRequestVersion
389
+ });
390
+ }
391
+ } finally {
392
+ if (requestIsCurrent() && loadingOperationVersionRef.current === loadingOperationVersion) setIsLoading(false);
393
+ }
394
+ })();
395
+ }, [
396
+ expandedPaths,
397
+ loadDirectory,
398
+ loadFile,
399
+ loadInfo,
400
+ root,
401
+ source
402
+ ]);
403
+ const stateIsCurrent = stateGeneration === sourceIdentityRef.current.generation;
404
+ const directoryError = [...new Set(Object.values(directoryErrorsByPath))].join("; ") || null;
405
+ const visibleSelectedPath = stateIsCurrent ? selectedPath : null;
406
+ const selectedFile = visibleSelectedPath ? activeAssetFile?.path === visibleSelectedPath ? activeAssetFile : filesByPath[visibleSelectedPath] ?? null : null;
407
+ return {
408
+ root,
409
+ entriesByDirectory: stateIsCurrent ? entriesByDirectory : EMPTY_ENTRIES_BY_DIRECTORY,
410
+ entryByPath: stateIsCurrent ? entryByPath : EMPTY_ENTRY_BY_PATH,
411
+ expandedPaths: stateIsCurrent ? expandedPaths : EMPTY_PATHS,
412
+ setExpandedPaths,
413
+ selectedPath: visibleSelectedPath,
414
+ selectFile,
415
+ selectedFile,
416
+ isLoading: !stateIsCurrent || isLoading,
417
+ loadingPaths: stateIsCurrent ? loadingPaths : EMPTY_PATHS,
418
+ error: stateIsCurrent ? directoryError : null,
419
+ info: stateIsCurrent ? info : null,
420
+ refresh
421
+ };
422
+ }
423
+ //#endregion
424
+ export { useWorkspace };
@@ -0,0 +1,32 @@
1
+ import { i as WorkspaceState } from "../Workspace-D39LxGvP.js";
2
+ import * as React from "react";
3
+
4
+ //#region src/components/WorkspaceBrowser.d.ts
5
+ interface WorkspaceBrowserProps {
6
+ workspace: WorkspaceState;
7
+ title?: React.ReactNode;
8
+ /** Leading workspace control, such as a host-owned Back to chat button. */
9
+ leading?: React.ReactNode;
10
+ actions?: React.ReactNode;
11
+ showFilter?: boolean;
12
+ filterPlaceholder?: string;
13
+ emptyState?: React.ReactNode;
14
+ onSelectFile?: (path: string) => void;
15
+ onBack?: () => void;
16
+ onForward?: () => void;
17
+ }
18
+ /** Workspace tree and filter surface, usable independently from the file preview. */
19
+ declare function WorkspaceBrowser({
20
+ workspace,
21
+ title,
22
+ leading,
23
+ actions,
24
+ showFilter,
25
+ filterPlaceholder,
26
+ emptyState,
27
+ onSelectFile,
28
+ onBack,
29
+ onForward
30
+ }: WorkspaceBrowserProps): React.JSX.Element;
31
+ //#endregion
32
+ export { WorkspaceBrowser, WorkspaceBrowserProps };
@@ -0,0 +1,103 @@
1
+ import { R as SearchIcon } from "../icons-CpfUer49.js";
2
+ import { Field } from "./Field.js";
3
+ import { i as FileTreeFolder, r as FileTreeFile, t as FileTree } from "../FileTree-CkVbIMWV.js";
4
+ import { WorkspaceHeader } from "./WorkspaceHeader.js";
5
+ import * as React from "react";
6
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
+ //#region src/components/WorkspaceBrowser.tsx
8
+ function compareFilteredWorkspaceFiles(left, right) {
9
+ return left.path.localeCompare(right.path) || left.name.localeCompare(right.name);
10
+ }
11
+ /** Workspace tree and filter surface, usable independently from the file preview. */
12
+ function WorkspaceBrowser({ workspace, title = "Workspace", leading, actions, showFilter = true, filterPlaceholder = "Filter files...", emptyState, onSelectFile, onBack, onForward }) {
13
+ const [filter, setFilter] = React.useState("");
14
+ const filterQuery = filter.trim().toLowerCase();
15
+ const { root, entriesByDirectory, entryByPath, expandedPaths, setExpandedPaths, selectedPath, selectFile, isLoading, error, info, refresh } = workspace;
16
+ const handleSelect = React.useCallback((path) => {
17
+ if (entryByPath.get(path)?.type === "directory") return;
18
+ selectFile(path);
19
+ onSelectFile?.(path);
20
+ }, [
21
+ entryByPath,
22
+ onSelectFile,
23
+ selectFile
24
+ ]);
25
+ const filteredFiles = React.useMemo(() => {
26
+ if (!filterQuery) return [];
27
+ return [...entryByPath.values()].filter((entry) => entry.type !== "directory" && entry.path.toLowerCase().includes(filterQuery)).sort(compareFilteredWorkspaceFiles);
28
+ }, [entryByPath, filterQuery]);
29
+ const renderEntry = (entry) => {
30
+ if (entry.type === "directory") return /* @__PURE__ */ jsx(FileTreeFolder, {
31
+ path: entry.path,
32
+ name: entry.name,
33
+ children: (entriesByDirectory[entry.path] ?? []).map(renderEntry)
34
+ }, entry.path);
35
+ return /* @__PURE__ */ jsx(FileTreeFile, {
36
+ path: entry.path,
37
+ name: entry.name
38
+ }, entry.path);
39
+ };
40
+ const rootEntries = entriesByDirectory[root] ?? [];
41
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(WorkspaceHeader, {
42
+ title,
43
+ fileCount: info?.fileCount,
44
+ leading,
45
+ actions,
46
+ isRefreshing: isLoading,
47
+ onBack,
48
+ onForward,
49
+ onRefresh: refresh
50
+ }), /* @__PURE__ */ jsxs("div", {
51
+ className: "workspace-explorer__body",
52
+ "data-workspace-browser-focus-target": "",
53
+ role: "region",
54
+ "aria-label": "Workspace files",
55
+ tabIndex: -1,
56
+ children: [showFilter ? /* @__PURE__ */ jsxs(Field.Root, {
57
+ className: "workspace-explorer__filter",
58
+ name: "workspace-filter",
59
+ children: [/* @__PURE__ */ jsx(Field.Label, {
60
+ className: "workspace-explorer__filter-label",
61
+ children: "Filter workspace files"
62
+ }), /* @__PURE__ */ jsxs("div", {
63
+ className: "workspace-explorer__filter-control",
64
+ children: [/* @__PURE__ */ jsx(SearchIcon, { "aria-hidden": "true" }), /* @__PURE__ */ jsx(Field.Control, {
65
+ type: "search",
66
+ value: filter,
67
+ onChange: (event) => setFilter(event.currentTarget.value),
68
+ placeholder: filterPlaceholder,
69
+ autoComplete: "off"
70
+ })]
71
+ })]
72
+ }) : null, error ? /* @__PURE__ */ jsx("div", {
73
+ className: "workspace-explorer__empty",
74
+ role: "alert",
75
+ children: error
76
+ }) : filterQuery ? filteredFiles.length > 0 ? /* @__PURE__ */ jsx(FileTree, {
77
+ className: "workspace-explorer__tree",
78
+ selectedPath,
79
+ onSelect: handleSelect,
80
+ "aria-label": "Workspace files",
81
+ children: filteredFiles.map((entry) => /* @__PURE__ */ jsx(FileTreeFile, {
82
+ path: entry.path,
83
+ name: entry.path
84
+ }, entry.path))
85
+ }) : /* @__PURE__ */ jsx("div", {
86
+ className: "workspace-explorer__empty",
87
+ children: "No matching files"
88
+ }) : rootEntries.length > 0 ? /* @__PURE__ */ jsx(FileTree, {
89
+ className: "workspace-explorer__tree",
90
+ expanded: new Set(expandedPaths),
91
+ onExpandedChange: setExpandedPaths,
92
+ selectedPath,
93
+ onSelect: handleSelect,
94
+ "aria-label": "Workspace files",
95
+ children: rootEntries.map(renderEntry)
96
+ }) : /* @__PURE__ */ jsx("div", {
97
+ className: "workspace-explorer__empty",
98
+ children: isLoading ? "Loading workspace..." : emptyState ?? "No workspace files"
99
+ })]
100
+ })] });
101
+ }
102
+ //#endregion
103
+ export { WorkspaceBrowser };