@parallelworks/ui 0.51.0 → 0.53.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 (250) hide show
  1. package/README.md +197 -17
  2. package/dist/ai/agent/toolStrings.d.ts +2 -0
  3. package/dist/ai/agent/toolStrings.js +20 -18
  4. package/dist/ai/ai.css +17 -3
  5. package/dist/ai/components/AllocationSelector.js +5 -1
  6. package/dist/ai/components/AttachmentManager.js +51 -42
  7. package/dist/ai/components/AttachmentUpload.d.ts +4 -2
  8. package/dist/ai/components/AttachmentUpload.js +9 -9
  9. package/dist/ai/components/BlockedGroupBanner.js +8 -14
  10. package/dist/ai/components/BranchNavigator.js +11 -12
  11. package/dist/ai/components/ChatEmptyState.js +12 -19
  12. package/dist/ai/components/ChatInput.d.ts +4 -3
  13. package/dist/ai/components/ChatInput.js +27 -13
  14. package/dist/ai/components/ChatMessage.js +45 -121
  15. package/dist/ai/components/ChatMessageList.d.ts +5 -2
  16. package/dist/ai/components/ChatMessageList.js +89 -51
  17. package/dist/ai/components/ChatSidebar.js +11 -7
  18. package/dist/ai/components/ChatThread.js +1 -13
  19. package/dist/ai/components/DragOverlay.js +3 -3
  20. package/dist/ai/components/MessageAttachments.d.ts +10 -0
  21. package/dist/ai/components/MessageAttachments.js +78 -0
  22. package/dist/ai/components/ModelSelector.js +3 -3
  23. package/dist/ai/components/PastedText.js +2 -2
  24. package/dist/ai/components/ProviderIssueBanner.js +19 -23
  25. package/dist/ai/components/ShareDialog.js +2 -2
  26. package/dist/ai/components/agent/ActivityLine.d.ts +0 -2
  27. package/dist/ai/components/agent/ActivityLine.js +8 -51
  28. package/dist/ai/components/agent/AgentMessageParts.js +114 -53
  29. package/dist/ai/core/ChatProvider.d.ts +16 -5
  30. package/dist/ai/core/ChatProvider.js +41 -8
  31. package/dist/ai/core/config.js +4 -3
  32. package/dist/ai/index.d.ts +1 -1
  33. package/dist/ai/index.js +3 -3
  34. package/dist/ai/strings.d.ts +29 -3
  35. package/dist/ai/strings.js +80 -26
  36. package/dist/ai/types.d.ts +4 -0
  37. package/dist/ai/ui/Notice.d.ts +2 -2
  38. package/dist/ai/ui/Notice.js +29 -62
  39. package/dist/ai/ui/sidebar.d.ts +5 -3
  40. package/dist/ai/ui/sidebar.js +22 -10
  41. package/dist/components/ActionMenu.d.ts +1 -0
  42. package/dist/components/ActionMenu.js +6 -1
  43. package/dist/components/AppLink.d.ts +26 -0
  44. package/dist/components/AppLink.js +51 -0
  45. package/dist/components/Avatar.d.ts +2 -1
  46. package/dist/components/Avatar.js +4 -2
  47. package/dist/components/Button.d.ts +15 -5
  48. package/dist/components/Button.js +47 -40
  49. package/dist/components/Callout.d.ts +31 -7
  50. package/dist/components/Callout.js +50 -19
  51. package/dist/components/Card.d.ts +11 -6
  52. package/dist/components/Card.js +14 -8
  53. package/dist/components/Checkbox.js +2 -1
  54. package/dist/components/ColorInput.js +5 -3
  55. package/dist/components/Combobox.js +49 -19
  56. package/dist/components/ConfirmModal.d.ts +19 -8
  57. package/dist/components/ConfirmModal.js +31 -53
  58. package/dist/components/CopyButton.d.ts +38 -0
  59. package/dist/components/CopyButton.js +68 -0
  60. package/dist/components/CreateModal.js +118 -111
  61. package/dist/components/DatePicker.js +12 -8
  62. package/dist/components/DescriptionList.d.ts +25 -5
  63. package/dist/components/DescriptionList.js +56 -22
  64. package/dist/components/Disclosure.js +1 -1
  65. package/dist/components/Drawer.js +10 -16
  66. package/dist/components/Field.d.ts +16 -5
  67. package/dist/components/Field.js +63 -8
  68. package/dist/components/IconButton.d.ts +14 -5
  69. package/dist/components/IconButton.js +25 -14
  70. package/dist/components/InfoTip.d.ts +12 -1
  71. package/dist/components/InfoTip.js +13 -2
  72. package/dist/components/Input.d.ts +14 -8
  73. package/dist/components/Input.js +46 -31
  74. package/dist/components/Loader.js +1 -1
  75. package/dist/components/MarkdownImpl.d.ts +1 -0
  76. package/dist/components/MarkdownImpl.js +1 -0
  77. package/dist/components/MenuEntries.d.ts +4 -0
  78. package/dist/components/MenuEntries.js +11 -12
  79. package/dist/components/Meter.js +5 -4
  80. package/dist/components/Modal.d.ts +28 -4
  81. package/dist/components/Modal.js +37 -14
  82. package/dist/components/Overview.d.ts +20 -12
  83. package/dist/components/Overview.js +14 -9
  84. package/dist/components/PageHeader.d.ts +47 -65
  85. package/dist/components/PageHeader.js +275 -153
  86. package/dist/components/PageHeaderAction.d.ts +67 -0
  87. package/dist/components/PageHeaderAction.js +107 -0
  88. package/dist/components/Pagination.js +6 -16
  89. package/dist/components/Popover.d.ts +4 -1
  90. package/dist/components/Popover.js +5 -3
  91. package/dist/components/Provider.d.ts +79 -19
  92. package/dist/components/Provider.js +140 -130
  93. package/dist/components/Radio.js +2 -1
  94. package/dist/components/RefreshButton.js +7 -8
  95. package/dist/components/RequiredMark.js +1 -1
  96. package/dist/components/Section.js +1 -1
  97. package/dist/components/Select.d.ts +4 -9
  98. package/dist/components/Select.js +24 -11
  99. package/dist/components/SettingModeOption.d.ts +1 -1
  100. package/dist/components/SettingModeOption.js +7 -1
  101. package/dist/components/SettingsCard.d.ts +5 -3
  102. package/dist/components/SettingsCard.js +27 -20
  103. package/dist/components/Slider.js +1 -1
  104. package/dist/components/StatusBadge.js +2 -2
  105. package/dist/components/Switch.js +5 -4
  106. package/dist/components/Table.d.ts +30 -20
  107. package/dist/components/Table.js +50 -73
  108. package/dist/components/Tabs.d.ts +3 -7
  109. package/dist/components/Tabs.js +6 -10
  110. package/dist/components/ThemeEditor.js +18 -8
  111. package/dist/components/Toast.d.ts +11 -3
  112. package/dist/components/Toast.js +45 -20
  113. package/dist/components/buttonClasses.js +1 -1
  114. package/dist/components/comboboxItems.d.ts +4 -0
  115. package/dist/components/comboboxItems.js +6 -1
  116. package/dist/components/dismiss.d.ts +12 -0
  117. package/dist/components/dismiss.js +19 -0
  118. package/dist/components/fieldBox.d.ts +4 -0
  119. package/dist/components/fieldBox.js +7 -3
  120. package/dist/components/floating.d.ts +3 -3
  121. package/dist/components/floating.js +1 -1
  122. package/dist/components/focus.d.ts +5 -0
  123. package/dist/components/focus.js +21 -1
  124. package/dist/components/markdownCodeBreaks.js +3 -4
  125. package/dist/components/pageHeaderStore.d.ts +41 -0
  126. package/dist/components/pageHeaderStore.js +67 -0
  127. package/dist/components/pathBreaks.d.ts +8 -0
  128. package/dist/components/pathBreaks.js +28 -0
  129. package/dist/components/segmented.js +1 -1
  130. package/dist/components/shortcutKey.d.ts +2 -1
  131. package/dist/components/shortcutKey.js +19 -2
  132. package/dist/components/splitter.js +1 -1
  133. package/dist/components/useCssIsDark.js +40 -18
  134. package/dist/components/useTheme.js +9 -10
  135. package/dist/dev.d.ts +9 -0
  136. package/dist/dev.js +14 -0
  137. package/dist/editor/Editor.d.ts +3 -2
  138. package/dist/editor/Editor.js +24 -5
  139. package/dist/editor/EditorField.d.ts +2 -1
  140. package/dist/editor/EditorField.js +11 -29
  141. package/dist/editor/FormCodePanel.d.ts +7 -3
  142. package/dist/editor/FormCodePanel.js +14 -7
  143. package/dist/editor/Monaco.d.ts +22 -6
  144. package/dist/editor/Monaco.js +177 -113
  145. package/dist/editor/editorModel.d.ts +1 -1
  146. package/dist/editor/editorModel.js +1 -1
  147. package/dist/editor/index.d.ts +6 -5
  148. package/dist/editor/index.js +5 -4
  149. package/dist/editor/languages.d.ts +24 -0
  150. package/dist/editor/languages.js +31 -0
  151. package/dist/editor/monacoFeatures.d.ts +7 -0
  152. package/dist/editor/monacoFeatures.js +19 -0
  153. package/dist/editor/themes.d.ts +8 -5
  154. package/dist/editor/themes.js +65 -32
  155. package/dist/editor/workers.d.ts +3 -3
  156. package/dist/editor/workers.js +8 -4
  157. package/dist/editor/yaml.d.ts +6 -2
  158. package/dist/editor/yaml.js +11 -2
  159. package/dist/editor/yamlLanguage.js +55 -38
  160. package/dist/file-explorer/FileExplorer.d.ts +18 -4
  161. package/dist/file-explorer/FileExplorer.js +204 -142
  162. package/dist/file-explorer/FileExplorerContext.js +1 -1
  163. package/dist/file-explorer/FilePreview/StreamedBadge.js +3 -1
  164. package/dist/file-explorer/FilePreview/Viewer.js +14 -10
  165. package/dist/file-explorer/FilePreview/index.js +4 -4
  166. package/dist/file-explorer/FileRow.d.ts +6 -2
  167. package/dist/file-explorer/FileRow.js +35 -17
  168. package/dist/file-explorer/FileRowsWindow.d.ts +2 -1
  169. package/dist/file-explorer/FileRowsWindow.js +36 -4
  170. package/dist/file-explorer/FileTable.d.ts +3 -1
  171. package/dist/file-explorer/FileTable.js +6 -3
  172. package/dist/file-explorer/TreeView.d.ts +5 -1
  173. package/dist/file-explorer/TreeView.js +86 -39
  174. package/dist/file-explorer/helpers.d.ts +2 -1
  175. package/dist/file-explorer/helpers.js +24 -23
  176. package/dist/file-explorer/lib/utils.d.ts +3 -0
  177. package/dist/file-explorer/lib/utils.js +6 -1
  178. package/dist/file-explorer/toasts.js +27 -19
  179. package/dist/file-explorer/treeRows.d.ts +6 -0
  180. package/dist/file-explorer/treeRows.js +19 -1
  181. package/dist/file-explorer/useNearEnd.js +3 -6
  182. package/dist/form/Fields/CheckboxGroupField.js +12 -5
  183. package/dist/form/Fields/DurationField.js +1 -1
  184. package/dist/form/Fields/LabelField.js +1 -1
  185. package/dist/form/Fields/ObjectField.d.ts +1 -1
  186. package/dist/form/Fields/ObjectField.js +3 -2
  187. package/dist/form/Fields/StringField.js +16 -29
  188. package/dist/form/Fields/TextAreaField.js +3 -4
  189. package/dist/form/Form.js +3 -8
  190. package/dist/form/Wizard/WizardNavigation.js +0 -3
  191. package/dist/form/Wizard/utils.js +2 -1
  192. package/dist/form/fieldFrame.d.ts +1 -1
  193. package/dist/form/fieldFrame.js +2 -2
  194. package/dist/form/types/fieldComponentTypes.d.ts +2 -1
  195. package/dist/graph/AnnotationBanner.d.ts +1 -2
  196. package/dist/graph/AnnotationBanner.js +30 -32
  197. package/dist/graph/Connectors.js +4 -1
  198. package/dist/graph/DependencyGraph.js +2 -2
  199. package/dist/graph/GraphEditor.js +11 -9
  200. package/dist/graph/GraphEditorDialogs.js +1 -1
  201. package/dist/graph/GraphNode.js +7 -4
  202. package/dist/graph/InputDialog.js +1 -1
  203. package/dist/graph/InputsEditor.js +14 -11
  204. package/dist/graph/MatrixGroup.js +9 -3
  205. package/dist/graph/Reveal.js +18 -10
  206. package/dist/graph/ShortcutsButton.d.ts +11 -2
  207. package/dist/graph/ShortcutsButton.js +14 -3
  208. package/dist/graph/TreeView.js +35 -18
  209. package/dist/graph/WorkflowSettingsDialog.js +1 -1
  210. package/dist/graph/editorFields.js +1 -1
  211. package/dist/graph/editorRows.js +16 -10
  212. package/dist/graph/editorStrings.d.ts +7 -0
  213. package/dist/graph/editorStrings.js +8 -1
  214. package/dist/graph/inputRefs.js +1 -1
  215. package/dist/graph/settingsViews.js +11 -18
  216. package/dist/graph/stepWith.js +1 -1
  217. package/dist/icons.d.ts +2 -0
  218. package/dist/icons.js +4 -2
  219. package/dist/index.d.ts +12 -12
  220. package/dist/index.js +16 -16
  221. package/dist/list/ActionToolbar.d.ts +42 -6
  222. package/dist/list/ActionToolbar.js +298 -101
  223. package/dist/list/ListPage.d.ts +15 -23
  224. package/dist/list/ListPage.js +42 -43
  225. package/dist/list/ListTable.d.ts +37 -7
  226. package/dist/list/ListTable.js +52 -12
  227. package/dist/list/ListViewControls.js +1 -1
  228. package/dist/list/UserHoverCard.js +7 -15
  229. package/dist/list/index.d.ts +2 -2
  230. package/dist/list/index.js +2 -2
  231. package/dist/list/listSearch.js +12 -10
  232. package/dist/list/listView.d.ts +10 -1
  233. package/dist/list/listView.js +15 -1
  234. package/dist/logviewer/LogViewer.d.ts +4 -2
  235. package/dist/logviewer/LogViewer.js +87 -69
  236. package/dist/logviewer/logviewer.css +3 -2
  237. package/dist/reducedMotion.d.ts +5 -0
  238. package/dist/reducedMotion.js +20 -0
  239. package/dist/safeUrl.d.ts +1 -1
  240. package/dist/safeUrl.js +4 -2
  241. package/dist/styles.css +1 -1
  242. package/package.json +5 -2
  243. package/dist/components/Breadcrumbs.d.ts +0 -37
  244. package/dist/components/Breadcrumbs.js +0 -90
  245. package/dist/components/CopyToClipboard.d.ts +0 -17
  246. package/dist/components/CopyToClipboard.js +0 -66
  247. package/dist/components/Sort.d.ts +0 -9
  248. package/dist/components/Sort.js +0 -42
  249. package/dist/file-explorer/FilePreview/CodePreviewEditor.d.ts +0 -6
  250. package/dist/file-explorer/FilePreview/CodePreviewEditor.js +0 -64
@@ -1,26 +1,29 @@
1
1
  import { cx } from "../cx.js";
2
- import { AccessIcon, ChevronDownIcon, ChevronRightIcon, CollapseIcon, CopyIcon, DownloadIcon, FileIcon, FileTextIcon, FolderIcon, LinkIcon, PreviewIcon, ShareIcon, TrashIcon, UploadIcon, WarningIcon } from "../icons.js";
2
+ import { buttonClasses } from "../components/buttonClasses.js";
3
+ import { AccessIcon, ChevronDownIcon, ChevronRightIcon, CollapseIcon, DownloadIcon, FileIcon, FileTextIcon, FolderIcon, LinkIcon, PreviewIcon, ShareIcon, TrashIcon, UploadIcon } from "../icons.js";
3
4
  import { MenuItem, MenuPopup, MenuSeparator } from "../components/Menu.js";
4
5
  import { safeUrl } from "../safeUrl.js";
5
- import { keyedByContent } from "../components/keys.js";
6
- import { buttonClasses } from "../components/buttonClasses.js";
7
6
  import { Loader } from "../components/Loader.js";
8
7
  import { toast } from "../components/Toast.js";
8
+ import { keyedByContent } from "../components/keys.js";
9
9
  import { Tooltip } from "../components/Tooltip.js";
10
- import { usePersistedState, useSlots, useStrings } from "../components/Provider.js";
10
+ import { useNavigation, usePersistedState, useSlots, useStrings } from "../components/Provider.js";
11
+ import { AppLink } from "../components/AppLink.js";
11
12
  import { useCopy } from "../components/useCopy.js";
12
13
  import { Button } from "../components/Button.js";
14
+ import { Callout } from "../components/Callout.js";
15
+ import { InfoTip } from "../components/InfoTip.js";
13
16
  import { ConfirmModal } from "../components/ConfirmModal.js";
14
17
  import { useContextMenu } from "../components/ContextMenu.js";
15
- import CopyToClipboard, { CopyCodeBlock } from "../components/CopyToClipboard.js";
18
+ import { CopyButton, CopyCodeBlock } from "../components/CopyButton.js";
16
19
  import { CreateModal } from "../components/CreateModal.js";
17
- import { InfoTip } from "../components/InfoTip.js";
18
20
  import { useSplitter } from "../components/splitter.js";
19
21
  import { formatBytes, formatDateTime } from "../format.js";
20
22
  import { RelativeTime } from "../components/relativeTime.js";
21
23
  import { RefreshButton } from "../components/RefreshButton.js";
22
24
  import { StatusBadge } from "../components/StatusBadge.js";
23
25
  import { Table } from "../components/Table.js";
26
+ import { Tabs } from "../components/Tabs.js";
24
27
  import { ListActionsHeader, ListSkeleton, listTableFixedProps, listTableProps } from "../list/ListTable.js";
25
28
  import { assembleRowMenu, useCopySubmenu } from "../list/rowMenu.js";
26
29
  import { calculateUploadNodesTotalSize, createTreeBuilder, getDirectoryNameError, getDirectoryObjectPath, getNodeChildren, getObjectKeyFromNode, getParentPath, getUploadNodesFromDataTransferItems, getUriScheme, pruneNodesInsideSelectedDirectories, removeLeadingAndTrailingSlashes } from "./lib/utils.js";
@@ -42,12 +45,10 @@ import { useCallback, useEffect, useEffectEvent, useLayoutEffect, useMemo, useRe
42
45
  import { DateTime } from "luxon";
43
46
  //#region src/file-explorer/FileExplorer.tsx
44
47
  function UriCard({ value }) {
45
- const { common } = useStrings();
48
+ const { fileExplorer: t } = useStrings();
46
49
  const scheme = getUriScheme(value);
47
- return /* @__PURE__ */ jsxs(CopyToClipboard, {
48
- text: value,
49
- showIcon: false,
50
- className: "group flex items-stretch rounded-lg border theme-border bg-(--theme-input-bg) overflow-hidden cursor-copy hover:border-(--theme-link)/50 transition-colors duration-150",
50
+ return /* @__PURE__ */ jsxs("div", {
51
+ className: "flex items-stretch overflow-hidden rounded-lg border theme-border bg-(--theme-input-bg)",
51
52
  children: [
52
53
  scheme && /* @__PURE__ */ jsx("span", {
53
54
  className: "shrink-0 inline-flex items-center px-3 bg-(--theme-muted-panel-bg) border-r theme-border font-mono text-[11px] font-semibold uppercase tracking-widest theme-muted-text",
@@ -58,13 +59,22 @@ function UriCard({ value }) {
58
59
  children: value
59
60
  }),
60
61
  /* @__PURE__ */ jsx("span", {
61
- className: "shrink-0 inline-flex items-center justify-center px-3 border-l theme-border theme-muted-text group-hover:text-(--theme-link) group-hover:bg-(--theme-link)/5 transition-colors duration-150",
62
- title: common.copyToClipboard,
63
- children: /* @__PURE__ */ jsx(CopyIcon, { className: "h-3.5 w-3.5" })
62
+ className: "shrink-0 inline-flex items-center border-l theme-border px-1.5",
63
+ children: /* @__PURE__ */ jsx(CopyButton, {
64
+ text: value,
65
+ "aria-label": t.preview.copyUri
66
+ })
64
67
  })
65
68
  ]
66
69
  });
67
70
  }
71
+ var breadcrumbClass = "max-w-[16rem] cursor-pointer truncate text-(--theme-muted-text-color) transition-colors hover:text-(--theme-app)";
72
+ /** `href` resolved against the page, as the browser's "Copy link" gives it. */
73
+ function absoluteUrl(href) {
74
+ const url = safeUrl(href);
75
+ if (!url || typeof window === "undefined") return url;
76
+ return new URL(url, window.location.href).href;
77
+ }
68
78
  var MAX_UPLOAD_SIZE = 85899345920;
69
79
  function isUploadSizeExceeded(size) {
70
80
  return size > MAX_UPLOAD_SIZE;
@@ -108,12 +118,13 @@ function TreeFrame({ treeOnly, sidebarWidth, onWidthChange, children }) {
108
118
  children: [children, /* @__PURE__ */ jsx("div", { ...splitter.separatorProps })]
109
119
  });
110
120
  }
111
- function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHierarchy = false, groups = [], groupsLoading = false, selectedPath, onPathChange, getProviderAndClient, treeOnly = false, initialExpandedPaths, onExpandedPathsChange, objectUris, downloadCommand, extraRowActions, headerAccessory }) {
121
+ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHierarchy = false, groups = [], groupsLoading = false, selectedPath, onPathChange, pathHref, getProviderAndClient, treeOnly = false, initialExpandedPaths, onExpandedPathsChange, objectUris, downloadCommand, extraRowActions, headerAccessory }) {
112
122
  const copySubmenu = useCopySubmenu();
113
123
  const t = useStrings().fileExplorer;
114
124
  const { common } = useStrings();
115
125
  const { copy } = useCopy();
116
126
  const slots = useSlots();
127
+ const { goTo } = useNavigation();
117
128
  const fileExplorerContext = useFileExplorer();
118
129
  const [listings, setListings] = useState(() => /* @__PURE__ */ new Map());
119
130
  const fetchesInFlightRef = useRef(/* @__PURE__ */ new Map());
@@ -144,7 +155,7 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
144
155
  if (treeMap[selectedPath]) return selectedPath;
145
156
  return `${selectedPath}/`;
146
157
  }, [selectedPath, treeMap]);
147
- const setSelectedPath = onPathChange;
158
+ const setSelectedPath = (path) => onPathChange ? onPathChange(path) : pathHref && goTo(pathHref(path));
148
159
  const [expandedPaths, setExpandedPaths] = useState(() => /* @__PURE__ */ new Set(["", ...initialExpandedPaths ?? []]));
149
160
  const onExpandedPathsChangeRef = useRef(onExpandedPathsChange);
150
161
  onExpandedPathsChangeRef.current = onExpandedPathsChange;
@@ -159,10 +170,12 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
159
170
  if (selectedNode?.type === "directory" && selectedNode.storageId) fetchNodeChildren(selectedNode, { replace: true });
160
171
  }, [refreshKey, selectedNode]);
161
172
  const [checkedItems, setCheckedItems] = useState(/* @__PURE__ */ new Set());
173
+ const [detailTab, setDetailTab] = useState("details");
162
174
  const [checkedItemsPath, setCheckedItemsPath] = useState(selectedPath);
163
175
  if (checkedItemsPath !== selectedPath) {
164
176
  setCheckedItemsPath(selectedPath);
165
177
  setCheckedItems(/* @__PURE__ */ new Set());
178
+ setDetailTab("details");
166
179
  }
167
180
  const selectedNodeChildren = useMemo(() => selectedNode ? getNodeChildren(parentToChildrenMap, selectedNode.path) : [], [parentToChildrenMap, selectedNode]);
168
181
  const findStorage = (storageId) => storages.find((s) => s.id === storageId);
@@ -242,7 +255,6 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
242
255
  const folderInputRef = useRef(null);
243
256
  const [deleteModalOpen, setDeleteModalOpen] = useState(false);
244
257
  const [pendingDelete, setPendingDelete] = useState(null);
245
- const [detailTab, setDetailTab] = useState("details");
246
258
  useEffect(() => clearPreviewCache, []);
247
259
  const { openMenu, contextMenu } = useContextMenu();
248
260
  const [sidebarWidth, setSidebarWidth] = usePersistedState(SIDEBAR_WIDTH_STORAGE_KEY, 300);
@@ -320,10 +332,10 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
320
332
  return { corsError: false };
321
333
  } catch (error) {
322
334
  const isCorsError = error instanceof CorsError;
323
- const errorMessage = isCorsError ? error.message || "CORS error" : error instanceof Error ? error.message : "Unknown error";
335
+ const errorMessage = error instanceof Error && error.message || t.messages.unknownError;
324
336
  if (owns()) {
325
337
  setListings((prev) => recordListingError(options?.replace ? clearListingsUnder(prev, node.path) : prev, node.path, errorMessage));
326
- updateConnectionIssuesMessage((prev) => new Map(prev).set(nodeStorageId, `Failed to load contents for ${node.displayName || node.name}: ${errorMessage}`));
338
+ updateConnectionIssuesMessage((prev) => new Map(prev).set(nodeStorageId, t.messages.loadFailed(node.displayName || node.name, errorMessage)));
327
339
  if (isCorsError) setHasCorsIssue((prev) => new Map(prev).set(nodeStorageId, true));
328
340
  }
329
341
  return { corsError: isCorsError };
@@ -566,6 +578,9 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
566
578
  const closePreview = () => {
567
579
  setPreviewOpen(false);
568
580
  };
581
+ const openFromTree = (node) => {
582
+ if (treeOnly && node.type === "file") openPreview(node);
583
+ };
569
584
  const openUserNode = (node) => {
570
585
  handleSelectTreeItem(node.path, node);
571
586
  if (!expandedPaths.has(node.path)) handleToggleExpand(node.path);
@@ -649,9 +664,16 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
649
664
  destructive: true,
650
665
  onClick: () => deleteNode(node)
651
666
  });
652
- const lead = [{
667
+ const open = {
653
668
  label: isFile ? t.preview.viewDetails : t.preview.openFolder,
654
- icon: isFile ? /* @__PURE__ */ jsx(FileTextIcon, {}) : /* @__PURE__ */ jsx(FolderIcon, {}),
669
+ icon: isFile ? /* @__PURE__ */ jsx(FileTextIcon, {}) : /* @__PURE__ */ jsx(FolderIcon, {})
670
+ };
671
+ const href = pathHref?.(node.path);
672
+ const lead = [href ? {
673
+ ...open,
674
+ href
675
+ } : {
676
+ ...open,
655
677
  onClick: () => handleSelectTreeItem(node.path, node)
656
678
  }];
657
679
  const uriExtras = uris.map((value) => ({
@@ -659,6 +681,12 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
659
681
  value,
660
682
  icon: /* @__PURE__ */ jsx(LinkIcon, {})
661
683
  }));
684
+ const pageUrl = absoluteUrl(href);
685
+ if (pageUrl) uriExtras.unshift({
686
+ label: t.preview.link,
687
+ value: pageUrl,
688
+ icon: /* @__PURE__ */ jsx(LinkIcon, {})
689
+ });
662
690
  return assembleRowMenu({
663
691
  lead,
664
692
  actions,
@@ -687,22 +715,34 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
687
715
  }
688
716
  if (chain.length === 0) return null;
689
717
  return /* @__PURE__ */ jsx("nav", {
690
- className: "flex min-w-0 flex-1 items-center gap-1 overflow-hidden text-[13px]",
691
- children: chain.map((node, i) => {
692
- const isLast = i === chain.length - 1;
693
- const label = node.displayName || node.name;
694
- return /* @__PURE__ */ jsxs("span", {
695
- className: "flex min-w-0 items-center gap-1",
696
- children: [i > 0 && /* @__PURE__ */ jsx(ChevronRightIcon, { className: "h-3 w-3 shrink-0 text-(--theme-muted-text-color)" }), isLast ? /* @__PURE__ */ jsx("span", {
697
- className: "truncate font-semibold text-(--theme-app)",
698
- children: label
699
- }) : /* @__PURE__ */ jsx("button", {
700
- type: "button",
701
- onClick: () => handleSelectTreeItem(node.path, node),
702
- className: "max-w-[16rem] cursor-pointer truncate text-(--theme-muted-text-color) transition-colors hover:text-(--theme-app)",
703
- children: label
704
- })]
705
- }, node.path);
718
+ "aria-label": t.chrome.location,
719
+ className: "flex min-w-0 flex-1 overflow-hidden text-[13px]",
720
+ children: /* @__PURE__ */ jsx("ol", {
721
+ className: "flex min-w-0 items-center gap-1",
722
+ children: chain.map((node, i) => {
723
+ const isLast = i === chain.length - 1;
724
+ const label = node.displayName || node.name;
725
+ return /* @__PURE__ */ jsxs("li", {
726
+ className: "flex min-w-0 items-center gap-1",
727
+ children: [i > 0 && /* @__PURE__ */ jsx(ChevronRightIcon, {
728
+ "aria-hidden": "true",
729
+ className: "h-3 w-3 shrink-0 text-(--theme-muted-text-color) rtl:rotate-180"
730
+ }), isLast ? /* @__PURE__ */ jsx("span", {
731
+ "aria-current": "location",
732
+ className: "truncate font-semibold text-(--theme-app)",
733
+ children: label
734
+ }) : pathHref ? /* @__PURE__ */ jsx(AppLink, {
735
+ href: pathHref(node.path),
736
+ className: breadcrumbClass,
737
+ children: label
738
+ }) : /* @__PURE__ */ jsx("button", {
739
+ type: "button",
740
+ onClick: () => handleSelectTreeItem(node.path, node),
741
+ className: breadcrumbClass,
742
+ children: label
743
+ })]
744
+ }, node.path);
745
+ })
706
746
  })
707
747
  });
708
748
  };
@@ -955,8 +995,10 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
955
995
  onToggleExpand: handleToggleExpand,
956
996
  onSelect: (path, node) => {
957
997
  handleSelectTreeItem(path, node);
958
- if (treeOnly && node.type === "file") openPreview(node);
998
+ openFromTree(node);
959
999
  },
1000
+ pathHref,
1001
+ onFollowLink: openFromTree,
960
1002
  onDropToFolder: onDropFiles,
961
1003
  onContextMenu: openNodeContextMenu,
962
1004
  onPreviewFile: openPreview,
@@ -998,18 +1040,28 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
998
1040
  children: t.chrome.storages
999
1041
  }),
1000
1042
  /* @__PURE__ */ jsx(ListActionsHeader, { actionCount: 1 }),
1001
- rootNodes.map((rootNode) => /* @__PURE__ */ jsx(UserRow, {
1002
- node: rootNode,
1003
- icon: getNodeIcon(rootNode),
1004
- storageCount: getNodeChildren(parentToChildrenMap, rootNode.path).length,
1005
- getItems: () => [{
1043
+ rootNodes.map((rootNode) => {
1044
+ const href = pathHref?.(rootNode.path);
1045
+ const open = {
1006
1046
  label: t.preview.open,
1007
- icon: /* @__PURE__ */ jsx(FolderIcon, {}),
1008
- onClick: () => openUserNode(rootNode)
1009
- }],
1010
- openMenu,
1011
- onOpen: openUserNode
1012
- }, rootNode.path))
1047
+ icon: /* @__PURE__ */ jsx(FolderIcon, {})
1048
+ };
1049
+ return /* @__PURE__ */ jsx(UserRow, {
1050
+ node: rootNode,
1051
+ icon: getNodeIcon(rootNode),
1052
+ href,
1053
+ storageCount: getNodeChildren(parentToChildrenMap, rootNode.path).length,
1054
+ getItems: () => [href ? {
1055
+ ...open,
1056
+ href
1057
+ } : {
1058
+ ...open,
1059
+ onClick: () => openUserNode(rootNode)
1060
+ }],
1061
+ openMenu,
1062
+ onOpen: openUserNode
1063
+ }, rootNode.path);
1064
+ })
1013
1065
  ]
1014
1066
  }), rootNodes.length === 0 && /* @__PURE__ */ jsx(NoDataAvailablePreview, {
1015
1067
  selectedStorage: null,
@@ -1056,33 +1108,41 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
1056
1108
  handleUploadInputChange(e.target.files, selectedNode);
1057
1109
  }
1058
1110
  }),
1059
- selectedNodeCanWrite && selectedNodeCanUpload && /* @__PURE__ */ jsx(Button, {
1060
- variant: "primary",
1061
- size: "sm",
1062
- "aria-label": t.createFolder.action,
1063
- icon: /* @__PURE__ */ jsx(FolderIcon, {}),
1064
- disabled: selectedNode.type === "file" || !selectedNode.storageId,
1065
- onClick: () => setCreateFolderTarget(selectedNode),
1066
- children: /* @__PURE__ */ jsx("span", {
1067
- className: "hidden @4xl:inline",
1068
- children: t.createFolder.action
1111
+ selectedNodeCanWrite && selectedNodeCanUpload && /* @__PURE__ */ jsx(Tooltip, {
1112
+ content: t.createFolder.action,
1113
+ side: "bottom",
1114
+ children: /* @__PURE__ */ jsx(Button, {
1115
+ variant: "outline",
1116
+ size: "sm",
1117
+ "aria-label": t.createFolder.action,
1118
+ icon: /* @__PURE__ */ jsx(FolderIcon, {}),
1119
+ disabled: selectedNode.type === "file" || !selectedNode.storageId,
1120
+ onClick: () => setCreateFolderTarget(selectedNode),
1121
+ children: /* @__PURE__ */ jsx("span", {
1122
+ className: "hidden @4xl:inline",
1123
+ children: t.createFolder.action
1124
+ })
1069
1125
  })
1070
1126
  }),
1071
- selectedNodeCanWrite && selectedNodeCanUpload && /* @__PURE__ */ jsxs(Menu.Root, { children: [/* @__PURE__ */ jsxs(Menu.Trigger, {
1072
- "aria-label": t.chrome.upload,
1073
- className: buttonClasses({
1074
- variant: "primary",
1075
- size: "sm"
1076
- }),
1077
- disabled: selectedNode.type === "file" || !selectedNode.storageId,
1078
- children: [
1079
- /* @__PURE__ */ jsx(UploadIcon, {}),
1080
- /* @__PURE__ */ jsx("span", {
1081
- className: "hidden @4xl:inline",
1082
- children: t.chrome.upload
1127
+ selectedNodeCanWrite && selectedNodeCanUpload && /* @__PURE__ */ jsxs(Menu.Root, { children: [/* @__PURE__ */ jsx(Tooltip, {
1128
+ content: t.chrome.upload,
1129
+ side: "bottom",
1130
+ children: /* @__PURE__ */ jsxs(Menu.Trigger, {
1131
+ "aria-label": t.chrome.upload,
1132
+ className: buttonClasses({
1133
+ variant: selectedNode.type === "directory" ? "primary" : "outline",
1134
+ size: "sm"
1083
1135
  }),
1084
- /* @__PURE__ */ jsx(ChevronDownIcon, {})
1085
- ]
1136
+ disabled: selectedNode.type === "file" || !selectedNode.storageId,
1137
+ children: [
1138
+ /* @__PURE__ */ jsx(UploadIcon, {}),
1139
+ /* @__PURE__ */ jsx("span", {
1140
+ className: "hidden @4xl:inline",
1141
+ children: t.chrome.upload
1142
+ }),
1143
+ /* @__PURE__ */ jsx(ChevronDownIcon, {})
1144
+ ]
1145
+ })
1086
1146
  }), /* @__PURE__ */ jsxs(MenuPopup, {
1087
1147
  align: "end",
1088
1148
  className: "w-36",
@@ -1094,21 +1154,25 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
1094
1154
  children: t.chrome.selectFolder
1095
1155
  })]
1096
1156
  })] }),
1097
- /* @__PURE__ */ jsxs(Menu.Root, { children: [/* @__PURE__ */ jsxs(Menu.Trigger, {
1098
- "aria-label": common.download,
1099
- className: buttonClasses({
1100
- variant: "primary",
1101
- size: "sm"
1102
- }),
1103
- disabled: checkedItems.size === 0 && selectedNode.type !== "file" || hasFolderSelected() || !selectedNode.storageId,
1104
- children: [
1105
- /* @__PURE__ */ jsx(DownloadIcon, {}),
1106
- /* @__PURE__ */ jsx("span", {
1107
- className: "hidden @4xl:inline",
1108
- children: common.download
1157
+ /* @__PURE__ */ jsxs(Menu.Root, { children: [/* @__PURE__ */ jsx(Tooltip, {
1158
+ content: common.download,
1159
+ side: "bottom",
1160
+ children: /* @__PURE__ */ jsxs(Menu.Trigger, {
1161
+ "aria-label": common.download,
1162
+ className: buttonClasses({
1163
+ variant: selectedNode.type === "file" ? "primary" : "outline",
1164
+ size: "sm"
1109
1165
  }),
1110
- /* @__PURE__ */ jsx(ChevronDownIcon, {})
1111
- ]
1166
+ disabled: checkedItems.size === 0 && selectedNode.type !== "file" || hasFolderSelected() || !selectedNode.storageId,
1167
+ children: [
1168
+ /* @__PURE__ */ jsx(DownloadIcon, {}),
1169
+ /* @__PURE__ */ jsx("span", {
1170
+ className: "hidden @4xl:inline",
1171
+ children: common.download
1172
+ }),
1173
+ /* @__PURE__ */ jsx(ChevronDownIcon, {})
1174
+ ]
1175
+ })
1112
1176
  }), /* @__PURE__ */ jsxs(MenuPopup, {
1113
1177
  align: "end",
1114
1178
  className: "w-72",
@@ -1121,7 +1185,7 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
1121
1185
  className: "text-sm text-center pb-1.5",
1122
1186
  children: downloadCommand.label
1123
1187
  }), /* @__PURE__ */ jsx(CopyCodeBlock, {
1124
- textToCopy: downloadCommandText,
1188
+ text: downloadCommandText,
1125
1189
  children: /* @__PURE__ */ jsx("div", {
1126
1190
  className: "overflow-x-auto text-xs",
1127
1191
  children: keyedByContent(downloadCommandText.split("\n"), (l) => l).map(({ key, item: line }) => /* @__PURE__ */ jsx("div", {
@@ -1132,28 +1196,37 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
1132
1196
  })]
1133
1197
  })] })]
1134
1198
  })] }),
1135
- groups.length > 0 && selectedNodeCanManageAccess && /* @__PURE__ */ jsx(Button, {
1136
- variant: "primary",
1137
- size: "sm",
1138
- "aria-label": t.chrome.access,
1139
- icon: /* @__PURE__ */ jsx(AccessIcon, {}),
1140
- disabled: !selectedNode.storageId,
1141
- onClick: () => setAccessDrawerOpen(true),
1142
- children: /* @__PURE__ */ jsx("span", {
1143
- className: "hidden @4xl:inline",
1144
- children: t.chrome.manageAccess
1199
+ groups.length > 0 && selectedNodeCanManageAccess && /* @__PURE__ */ jsx(Tooltip, {
1200
+ content: t.chrome.manageAccess,
1201
+ side: "bottom",
1202
+ children: /* @__PURE__ */ jsx(Button, {
1203
+ variant: "outline",
1204
+ size: "sm",
1205
+ "aria-label": t.chrome.access,
1206
+ icon: /* @__PURE__ */ jsx(AccessIcon, {}),
1207
+ disabled: !selectedNode.storageId,
1208
+ onClick: () => setAccessDrawerOpen(true),
1209
+ children: /* @__PURE__ */ jsx("span", {
1210
+ className: "hidden @4xl:inline",
1211
+ children: t.chrome.manageAccess
1212
+ })
1145
1213
  })
1146
1214
  }),
1147
- selectedNodeCanDelete && /* @__PURE__ */ jsx(Button, {
1148
- variant: "danger",
1149
- size: "sm",
1150
- "aria-label": common.delete,
1151
- icon: /* @__PURE__ */ jsx(TrashIcon, {}),
1152
- disabled: checkedItems.size === 0 && selectedNode.type !== "file" || !selectedNode.storageId,
1153
- onClick: onDeleteClick,
1154
- children: /* @__PURE__ */ jsx("span", {
1155
- className: "hidden @4xl:inline",
1156
- children: common.delete
1215
+ selectedNodeCanDelete && /* @__PURE__ */ jsx(Tooltip, {
1216
+ content: common.delete,
1217
+ side: "bottom",
1218
+ children: /* @__PURE__ */ jsx(Button, {
1219
+ variant: "outline",
1220
+ size: "sm",
1221
+ "aria-label": common.delete,
1222
+ icon: /* @__PURE__ */ jsx(TrashIcon, {}),
1223
+ className: "*:text-(--theme-error-text)",
1224
+ disabled: checkedItems.size === 0 && selectedNode.type !== "file" || !selectedNode.storageId,
1225
+ onClick: onDeleteClick,
1226
+ children: /* @__PURE__ */ jsx("span", {
1227
+ className: "hidden @4xl:inline",
1228
+ children: common.delete
1229
+ })
1157
1230
  })
1158
1231
  })
1159
1232
  ]
@@ -1175,6 +1248,7 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
1175
1248
  onOpen: (n) => handleSelectTreeItem(n.path, n),
1176
1249
  onToggleCheck: handleItemCheckbox,
1177
1250
  onPreview: openPreview,
1251
+ pathHref,
1178
1252
  loadMore: loadMoreProps
1179
1253
  }, selectedNode.path) : /* @__PURE__ */ jsxs("div", {
1180
1254
  className: "h-full flex flex-col",
@@ -1202,22 +1276,20 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
1202
1276
  const createdDt = selectedNode.created ? DateTime.fromISO(selectedNode.created) : null;
1203
1277
  const previewable = canPreview(selectedNode);
1204
1278
  const effectiveTab = previewable ? detailTab : "details";
1205
- const tabClass = (active) => cx("mx-2.5 border-b-2 px-1 py-2.5 text-[13px] font-medium cursor-pointer transition-colors", active ? "theme-text border-(--theme-accent)" : "theme-muted-text border-transparent hover:theme-text");
1206
1279
  return /* @__PURE__ */ jsxs("div", {
1207
1280
  className: "flex h-full min-h-0 flex-col",
1208
- children: [/* @__PURE__ */ jsxs("div", {
1209
- className: "flex shrink-0 items-center border-b theme-border px-3",
1210
- children: [/* @__PURE__ */ jsx("button", {
1211
- type: "button",
1212
- className: tabClass(effectiveTab === "details"),
1213
- onClick: () => setDetailTab("details"),
1214
- children: t.preview.detailsTab
1215
- }), previewable && /* @__PURE__ */ jsx("button", {
1216
- type: "button",
1217
- className: tabClass(effectiveTab === "preview"),
1218
- onClick: () => setDetailTab("preview"),
1219
- children: t.preview.previewTab
1220
- })]
1281
+ children: [/* @__PURE__ */ jsx(Tabs, {
1282
+ label: selectedNode.name,
1283
+ items: [{
1284
+ value: "details",
1285
+ label: t.preview.detailsTab
1286
+ }, ...previewable ? [{
1287
+ value: "preview",
1288
+ label: t.preview.previewTab
1289
+ }] : []],
1290
+ value: effectiveTab,
1291
+ onValueChange: setDetailTab,
1292
+ className: "shrink-0 px-3"
1221
1293
  }), effectiveTab === "preview" && previewable ? /* @__PURE__ */ jsx(FilePreviewInline, {
1222
1294
  node: selectedNode,
1223
1295
  storage: selectedStorage ?? null,
@@ -1274,12 +1346,12 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
1274
1346
  node: selectedNode,
1275
1347
  onShare: onShareFileButtonClick
1276
1348
  }), /* @__PURE__ */ jsx(InfoTip, {
1277
- text: "This will generate a pre-signed URL for this file. Anyone with this link can temporarily access and download the file, even if they don't have an account. The link will automatically expire after 12 hours.",
1349
+ text: t.chrome.shareHelp,
1278
1350
  side: "right"
1279
1351
  })]
1280
1352
  }),
1281
1353
  /* @__PURE__ */ jsxs("div", {
1282
- className: "px-6 py-5 mt-5 border-t theme-border",
1354
+ className: cx("px-6 py-5", (uris.length > 0 || selectedNodeCanShare) && "mt-5 border-t theme-border"),
1283
1355
  children: [/* @__PURE__ */ jsx("h3", {
1284
1356
  className: "text-[11px] font-semibold uppercase tracking-widest theme-muted-text mb-3",
1285
1357
  children: t.chrome.details
@@ -1388,8 +1460,8 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
1388
1460
  children: /* @__PURE__ */ jsxs("div", {
1389
1461
  className: "text-sm flex flex-col gap-2 mt-2 text-left",
1390
1462
  children: [
1391
- /* @__PURE__ */ jsx("ul", {
1392
- className: "list-disc pl-5 max-h-40 overflow-auto theme-muted-panel py-1",
1463
+ /* @__PURE__ */ jsx("div", {
1464
+ className: "max-h-40 overflow-auto theme-muted-panel py-1 pl-3",
1393
1465
  children: pendingUpload?.uploadNodes && renderUploadNodes(pendingUpload.uploadNodes)
1394
1466
  }),
1395
1467
  /* @__PURE__ */ jsxs("div", { children: [
@@ -1409,26 +1481,16 @@ function FileExplorer({ storages, onRefresh, refreshKey, onOpenFile, showUserHie
1409
1481
  }),
1410
1482
  " ",
1411
1483
  /* @__PURE__ */ jsx("span", {
1412
- className: cx(isUploadSizeExceeded(pendingUpload?.totalSize ?? 0) && "text-amber-800 font-semibold"),
1484
+ className: cx(isUploadSizeExceeded(pendingUpload?.totalSize ?? 0) && "text-(--theme-warning-text) font-semibold"),
1413
1485
  children: formatBytes(pendingUpload?.totalSize ?? 0)
1414
1486
  })
1415
1487
  ]
1416
1488
  }),
1417
- isUploadSizeExceeded(pendingUpload?.totalSize ?? 0) && /* @__PURE__ */ jsx("div", {
1418
- className: "mt-3 p-3 bg-amber-50 border border-amber-200 rounded-lg",
1419
- children: /* @__PURE__ */ jsxs("div", {
1420
- className: "flex items-start gap-2",
1421
- children: [/* @__PURE__ */ jsx(WarningIcon, { className: "w-4 h-4 text-amber-600 shrink-0 mt-0.5" }), /* @__PURE__ */ jsxs("div", {
1422
- className: "text-amber-800",
1423
- children: [/* @__PURE__ */ jsx("div", {
1424
- className: "font-semibold mb-1",
1425
- children: t.confirmUpload.sizeLimitTitle
1426
- }), /* @__PURE__ */ jsxs("div", {
1427
- className: "text-sm",
1428
- children: [/* @__PURE__ */ jsx("p", { children: t.confirmUpload.sizeLimitBody(formatBytes(pendingUpload?.totalSize ?? 0), formatBytes(MAX_UPLOAD_SIZE)) }), /* @__PURE__ */ jsx("p", { children: t.confirmUpload.sizeLimitHint })]
1429
- })]
1430
- })]
1431
- })
1489
+ isUploadSizeExceeded(pendingUpload?.totalSize ?? 0) && /* @__PURE__ */ jsxs(Callout, {
1490
+ tone: "warning",
1491
+ title: t.confirmUpload.sizeLimitTitle,
1492
+ className: "mt-3",
1493
+ children: [/* @__PURE__ */ jsx("p", { children: t.confirmUpload.sizeLimitBody(formatBytes(pendingUpload?.totalSize ?? 0), formatBytes(MAX_UPLOAD_SIZE)) }), /* @__PURE__ */ jsx("p", { children: t.confirmUpload.sizeLimitHint })]
1432
1494
  })
1433
1495
  ]
1434
1496
  })
@@ -1,5 +1,5 @@
1
- import { keyedByContent } from "../components/keys.js";
2
1
  import { toast } from "../components/Toast.js";
2
+ import { keyedByContent } from "../components/keys.js";
3
3
  import { useStrings } from "../components/Provider.js";
4
4
  import { mapWithConcurrency } from "./lib/batch.js";
5
5
  import { calculateUploadNodesTotalSize, getUploadSessionETA, removeLeadingSlash } from "./lib/utils.js";
@@ -1,4 +1,6 @@
1
+ import { cx } from "../../cx.js";
1
2
  import { LockIcon } from "../../icons.js";
3
+ import { toneSurface } from "../../components/tone.js";
2
4
  import { useStrings } from "../../components/Provider.js";
3
5
  import { InfoTip } from "../../components/InfoTip.js";
4
6
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -7,7 +9,7 @@ function StreamedBadge() {
7
9
  const t = useStrings().fileExplorer;
8
10
  return /* @__PURE__ */ jsxs(InfoTip, {
9
11
  text: t.preview.streamedTooltip,
10
- className: "shrink-0 gap-1 rounded-full border border-green-500/40 bg-green-500/15 px-2 py-0.5 text-[11px] text-green-600",
12
+ className: cx("shrink-0 gap-1 rounded-full border px-2 py-0.5 text-[11px]", toneSurface.success),
11
13
  children: [/* @__PURE__ */ jsx(LockIcon, { className: "h-2.5 w-2.5" }), t.preview.streamed]
12
14
  });
13
15
  }
@@ -1,11 +1,12 @@
1
1
  import { cx } from "../../cx.js";
2
2
  import { DownloadIcon, FileIcon, LockIcon, MusicIcon, ZipIcon } from "../../icons.js";
3
- import { positionKeys, withPositionKeys } from "../../components/keys.js";
4
3
  import { Loader } from "../../components/Loader.js";
4
+ import { positionKeys, withPositionKeys } from "../../components/keys.js";
5
5
  import { useStrings } from "../../components/Provider.js";
6
6
  import { Button } from "../../components/Button.js";
7
7
  import Markdown from "../../components/Markdown.js";
8
8
  import { formatBytes } from "../../format.js";
9
+ import { Editor } from "../../editor/Editor.js";
9
10
  import { getFileExtension } from "../lib/utils.js";
10
11
  import { getMonacoLanguage, previewLimitsFor } from "./previewType.js";
11
12
  import { CorsIssuePreview } from "../helpers.js";
@@ -14,9 +15,8 @@ import { countLines } from "./readCappedBytes.js";
14
15
  import { useObjectBlobUrl } from "./useObjectBlobUrl.js";
15
16
  import { useObjectText } from "./useObjectText.js";
16
17
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
17
- import { Suspense, lazy, useCallback, useMemo, useState } from "react";
18
+ import { useCallback, useMemo, useState } from "react";
18
19
  //#region src/file-explorer/FilePreview/Viewer.tsx
19
- var CodePreviewEditor = lazy(() => import("./CodePreviewEditor.js"));
20
20
  var PREVIEW_MARKDOWN_CONTROLS = {
21
21
  table: { fullscreen: false },
22
22
  mermaid: { fullscreen: false }
@@ -279,12 +279,16 @@ function CodeView({ node, url, onDownload, storage, onCorsRetry }) {
279
279
  controls: PREVIEW_MARKDOWN_CONTROLS,
280
280
  children: text ?? ""
281
281
  })
282
- }) : /* @__PURE__ */ jsx(Suspense, {
283
- fallback: /* @__PURE__ */ jsx(PreviewLoading, {}),
284
- children: /* @__PURE__ */ jsx(CodePreviewEditor, {
285
- value: text ?? "",
286
- language
287
- })
282
+ }) : /* @__PURE__ */ jsx(Editor, {
283
+ readOnly: true,
284
+ value: text ?? "",
285
+ language,
286
+ ariaLabel: node.name,
287
+ className: "!rounded-none !border-0",
288
+ fontSize: 12,
289
+ minimap: { enabled: false },
290
+ overviewRulerLanes: 0,
291
+ wordWrap: "off"
288
292
  })
289
293
  })
290
294
  })]
@@ -439,7 +443,7 @@ function NotebookOutputView({ output }) {
439
443
  children: joinSource(output.text)
440
444
  });
441
445
  if (output.output_type === "error") return /* @__PURE__ */ jsx("pre", {
442
- className: "mt-2 overflow-auto rounded-lg bg-red-500/15 px-3 py-2 font-mono text-[11px] text-red-500",
446
+ className: "mt-2 overflow-auto rounded-lg bg-(--theme-error-muted) px-3 py-2 font-mono text-[11px] text-(--theme-error-text)",
443
447
  children: stripAnsi((output.traceback ?? []).join("\n"))
444
448
  });
445
449
  const plain = output.data?.["text/plain"];