dsh-plugin-core 0.2.14 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (431) hide show
  1. package/README.md +52 -83
  2. package/dist/design/tokens-css.d.ts +1 -1
  3. package/dist/design/tokens-css.d.ts.map +1 -1
  4. package/dist/design/tokens-css.generated.d.ts +2 -0
  5. package/dist/design/tokens-css.generated.d.ts.map +1 -0
  6. package/dist/design/tokens-css.generated.js +4 -0
  7. package/dist/design/tokens-css.generated.js.map +1 -0
  8. package/dist/design/tokens-css.js +1 -252
  9. package/dist/design/tokens-css.js.map +1 -1
  10. package/dist/explorer/FileBrowser.d.ts +41 -0
  11. package/dist/explorer/FileBrowser.d.ts.map +1 -0
  12. package/dist/explorer/FileBrowser.js +659 -0
  13. package/dist/explorer/FileBrowser.js.map +1 -0
  14. package/dist/explorer/explorer-css.d.ts +1 -1
  15. package/dist/explorer/explorer-css.d.ts.map +1 -1
  16. package/dist/explorer/explorer-css.generated.d.ts +2 -0
  17. package/dist/explorer/explorer-css.generated.d.ts.map +1 -0
  18. package/dist/explorer/explorer-css.generated.js +4 -0
  19. package/dist/explorer/explorer-css.generated.js.map +1 -0
  20. package/dist/explorer/explorer-css.js +1 -31
  21. package/dist/explorer/explorer-css.js.map +1 -1
  22. package/dist/explorer/index.d.ts +4 -2
  23. package/dist/explorer/index.d.ts.map +1 -1
  24. package/dist/explorer/index.js +4 -2
  25. package/dist/explorer/index.js.map +1 -1
  26. package/dist/explorer/open.d.ts +103 -0
  27. package/dist/explorer/open.d.ts.map +1 -0
  28. package/dist/explorer/open.js +282 -0
  29. package/dist/explorer/open.js.map +1 -0
  30. package/dist/explorer/preview/BytesPreview.d.ts +13 -0
  31. package/dist/explorer/preview/BytesPreview.d.ts.map +1 -0
  32. package/dist/explorer/preview/BytesPreview.js +56 -0
  33. package/dist/explorer/preview/BytesPreview.js.map +1 -0
  34. package/dist/explorer/preview/HtmlPreview.d.ts +18 -0
  35. package/dist/explorer/preview/HtmlPreview.d.ts.map +1 -0
  36. package/dist/explorer/preview/HtmlPreview.js +112 -0
  37. package/dist/explorer/preview/HtmlPreview.js.map +1 -0
  38. package/dist/explorer/preview/OfficePreview.d.ts +11 -0
  39. package/dist/explorer/preview/OfficePreview.d.ts.map +1 -0
  40. package/dist/explorer/preview/OfficePreview.js +53 -0
  41. package/dist/explorer/preview/OfficePreview.js.map +1 -0
  42. package/dist/explorer/preview/TextPreview.d.ts +17 -0
  43. package/dist/explorer/preview/TextPreview.d.ts.map +1 -0
  44. package/dist/explorer/preview/TextPreview.js +95 -0
  45. package/dist/explorer/preview/TextPreview.js.map +1 -0
  46. package/dist/explorer/preview/index.d.ts +10 -3
  47. package/dist/explorer/preview/index.d.ts.map +1 -1
  48. package/dist/explorer/preview/index.js +52 -55
  49. package/dist/explorer/preview/index.js.map +1 -1
  50. package/dist/explorer/preview/md-labels.d.ts +3 -0
  51. package/dist/explorer/preview/md-labels.d.ts.map +1 -0
  52. package/dist/explorer/preview/md-labels.js +12 -0
  53. package/dist/explorer/preview/md-labels.js.map +1 -0
  54. package/dist/explorer/types.d.ts +186 -4
  55. package/dist/explorer/types.d.ts.map +1 -1
  56. package/dist/explorer/types.js +401 -14
  57. package/dist/explorer/types.js.map +1 -1
  58. package/dist/host/index.d.ts +66 -0
  59. package/dist/host/index.d.ts.map +1 -0
  60. package/dist/host/index.js +60 -0
  61. package/dist/host/index.js.map +1 -0
  62. package/dist/session/SessionViewModal.d.ts +42 -0
  63. package/dist/session/SessionViewModal.d.ts.map +1 -0
  64. package/dist/session/SessionViewModal.js +997 -0
  65. package/dist/session/SessionViewModal.js.map +1 -0
  66. package/dist/session/changes.d.ts +73 -0
  67. package/dist/session/changes.d.ts.map +1 -0
  68. package/dist/session/changes.js +134 -0
  69. package/dist/session/changes.js.map +1 -0
  70. package/dist/session/faces.d.ts +198 -0
  71. package/dist/session/faces.d.ts.map +1 -0
  72. package/dist/session/faces.js +17 -0
  73. package/dist/session/faces.js.map +1 -0
  74. package/dist/session/index.d.ts +5 -23
  75. package/dist/session/index.d.ts.map +1 -1
  76. package/dist/session/index.js +25 -70
  77. package/dist/session/index.js.map +1 -1
  78. package/dist/session/mirror/ChangedFileDiff.d.ts +22 -0
  79. package/dist/session/mirror/ChangedFileDiff.d.ts.map +1 -0
  80. package/dist/session/mirror/ChangedFileDiff.js +157 -0
  81. package/dist/session/mirror/ChangedFileDiff.js.map +1 -0
  82. package/dist/session/mirror/ChangedFilesCard.d.ts +18 -0
  83. package/dist/session/mirror/ChangedFilesCard.d.ts.map +1 -0
  84. package/dist/session/mirror/ChangedFilesCard.js +158 -0
  85. package/dist/session/mirror/ChangedFilesCard.js.map +1 -0
  86. package/dist/session/mirror/ChatGroupSeat.d.ts +24 -0
  87. package/dist/session/mirror/ChatGroupSeat.d.ts.map +1 -0
  88. package/dist/session/mirror/ChatGroupSeat.js +134 -0
  89. package/dist/session/mirror/ChatGroupSeat.js.map +1 -0
  90. package/dist/session/mirror/ChatNodeSeat.d.ts +43 -0
  91. package/dist/session/mirror/ChatNodeSeat.d.ts.map +1 -0
  92. package/dist/session/mirror/ChatNodeSeat.js +133 -0
  93. package/dist/session/mirror/ChatNodeSeat.js.map +1 -0
  94. package/dist/session/mirror/ChatView.d.ts +47 -0
  95. package/dist/session/mirror/ChatView.d.ts.map +1 -0
  96. package/dist/session/mirror/ChatView.js +127 -0
  97. package/dist/session/mirror/ChatView.js.map +1 -0
  98. package/dist/session/mirror/CommandCard.d.ts +20 -0
  99. package/dist/session/mirror/CommandCard.d.ts.map +1 -0
  100. package/dist/session/mirror/CommandCard.js +69 -0
  101. package/dist/session/mirror/CommandCard.js.map +1 -0
  102. package/dist/session/mirror/Deliverables.d.ts +24 -0
  103. package/dist/session/mirror/Deliverables.d.ts.map +1 -0
  104. package/dist/session/mirror/Deliverables.js +134 -0
  105. package/dist/session/mirror/Deliverables.js.map +1 -0
  106. package/dist/session/mirror/GenericCommandCard.d.ts +25 -0
  107. package/dist/session/mirror/GenericCommandCard.d.ts.map +1 -0
  108. package/dist/session/mirror/GenericCommandCard.js +567 -0
  109. package/dist/session/mirror/GenericCommandCard.js.map +1 -0
  110. package/dist/session/mirror/MessageIconActions.d.ts +16 -0
  111. package/dist/session/mirror/MessageIconActions.d.ts.map +1 -0
  112. package/dist/session/mirror/MessageIconActions.js +71 -0
  113. package/dist/session/mirror/MessageIconActions.js.map +1 -0
  114. package/dist/session/mirror/MessageItem.d.ts +66 -0
  115. package/dist/session/mirror/MessageItem.d.ts.map +1 -0
  116. package/dist/session/mirror/MessageItem.js +135 -0
  117. package/dist/session/mirror/MessageItem.js.map +1 -0
  118. package/dist/session/mirror/ReasoningRow.d.ts +11 -0
  119. package/dist/session/mirror/ReasoningRow.d.ts.map +1 -0
  120. package/dist/session/mirror/ReasoningRow.js +49 -0
  121. package/dist/session/mirror/ReasoningRow.js.map +1 -0
  122. package/dist/session/mirror/StatDialog.d.ts +20 -0
  123. package/dist/session/mirror/StatDialog.d.ts.map +1 -0
  124. package/dist/session/mirror/StatDialog.js +36 -0
  125. package/dist/session/mirror/StatDialog.js.map +1 -0
  126. package/dist/session/mirror/TurnProcessNodeView.d.ts +10 -0
  127. package/dist/session/mirror/TurnProcessNodeView.d.ts.map +1 -0
  128. package/dist/session/mirror/TurnProcessNodeView.js +68 -0
  129. package/dist/session/mirror/TurnProcessNodeView.js.map +1 -0
  130. package/dist/session/mirror/TurnTailNodeView.d.ts +32 -0
  131. package/dist/session/mirror/TurnTailNodeView.d.ts.map +1 -0
  132. package/dist/session/mirror/TurnTailNodeView.js +48 -0
  133. package/dist/session/mirror/TurnTailNodeView.js.map +1 -0
  134. package/dist/session/mirror/TurnTriggerNodeView.d.ts +14 -0
  135. package/dist/session/mirror/TurnTriggerNodeView.d.ts.map +1 -0
  136. package/dist/session/mirror/TurnTriggerNodeView.js +87 -0
  137. package/dist/session/mirror/TurnTriggerNodeView.js.map +1 -0
  138. package/dist/session/mirror/TurnUsagePanel.d.ts +21 -0
  139. package/dist/session/mirror/TurnUsagePanel.d.ts.map +1 -0
  140. package/dist/session/mirror/TurnUsagePanel.js +41 -0
  141. package/dist/session/mirror/TurnUsagePanel.js.map +1 -0
  142. package/dist/session/mirror/message-chrome.d.ts +33 -0
  143. package/dist/session/mirror/message-chrome.d.ts.map +1 -0
  144. package/dist/session/mirror/message-chrome.js +158 -0
  145. package/dist/session/mirror/message-chrome.js.map +1 -0
  146. package/dist/session/mirror/process-groups.d.ts +56 -0
  147. package/dist/session/mirror/process-groups.d.ts.map +1 -0
  148. package/dist/session/mirror/process-groups.js +202 -0
  149. package/dist/session/mirror/process-groups.js.map +1 -0
  150. package/dist/session/official-classes.d.ts +28 -0
  151. package/dist/session/official-classes.d.ts.map +1 -0
  152. package/dist/session/official-classes.js +146 -0
  153. package/dist/session/official-classes.js.map +1 -0
  154. package/dist/session/open-session-view.d.ts +17 -0
  155. package/dist/session/open-session-view.d.ts.map +1 -0
  156. package/dist/session/open-session-view.js +136 -0
  157. package/dist/session/open-session-view.js.map +1 -0
  158. package/dist/session/session-css.d.ts +1 -1
  159. package/dist/session/session-css.d.ts.map +1 -1
  160. package/dist/session/session-css.generated.d.ts +2 -0
  161. package/dist/session/session-css.generated.d.ts.map +1 -0
  162. package/dist/session/session-css.generated.js +4 -0
  163. package/dist/session/session-css.generated.js.map +1 -0
  164. package/dist/session/session-css.js +1 -17
  165. package/dist/session/session-css.js.map +1 -1
  166. package/dist/ui/AlertModal.d.ts +28 -0
  167. package/dist/ui/AlertModal.d.ts.map +1 -0
  168. package/dist/ui/AlertModal.js +29 -0
  169. package/dist/ui/AlertModal.js.map +1 -0
  170. package/dist/ui/Button.d.ts.map +1 -1
  171. package/dist/ui/Button.js +14 -1
  172. package/dist/ui/Button.js.map +1 -1
  173. package/dist/ui/Card.d.ts +4 -2
  174. package/dist/ui/Card.d.ts.map +1 -1
  175. package/dist/ui/Card.js +12 -6
  176. package/dist/ui/Card.js.map +1 -1
  177. package/dist/ui/Chip.d.ts +9 -1
  178. package/dist/ui/Chip.d.ts.map +1 -1
  179. package/dist/ui/Chip.js +8 -2
  180. package/dist/ui/Chip.js.map +1 -1
  181. package/dist/ui/CodeViewer.d.ts +36 -0
  182. package/dist/ui/CodeViewer.d.ts.map +1 -0
  183. package/dist/ui/CodeViewer.js +90 -0
  184. package/dist/ui/CodeViewer.js.map +1 -0
  185. package/dist/ui/ConfirmModal.d.ts +30 -0
  186. package/dist/ui/ConfirmModal.d.ts.map +1 -0
  187. package/dist/ui/ConfirmModal.js +23 -0
  188. package/dist/ui/ConfirmModal.js.map +1 -0
  189. package/dist/ui/DateTimePicker.d.ts +45 -0
  190. package/dist/ui/DateTimePicker.d.ts.map +1 -0
  191. package/dist/ui/DateTimePicker.js +447 -0
  192. package/dist/ui/DateTimePicker.js.map +1 -0
  193. package/dist/ui/Field.d.ts +11 -2
  194. package/dist/ui/Field.d.ts.map +1 -1
  195. package/dist/ui/Field.js +15 -5
  196. package/dist/ui/Field.js.map +1 -1
  197. package/dist/ui/MarqueeText.d.ts.map +1 -1
  198. package/dist/ui/MarqueeText.js +3 -1
  199. package/dist/ui/MarqueeText.js.map +1 -1
  200. package/dist/ui/Modal.d.ts +25 -3
  201. package/dist/ui/Modal.d.ts.map +1 -1
  202. package/dist/ui/Modal.js +41 -7
  203. package/dist/ui/Modal.js.map +1 -1
  204. package/dist/ui/ModelPicker.d.ts +25 -12
  205. package/dist/ui/ModelPicker.d.ts.map +1 -1
  206. package/dist/ui/ModelPicker.js +67 -19
  207. package/dist/ui/ModelPicker.js.map +1 -1
  208. package/dist/ui/PanelDock.d.ts +127 -0
  209. package/dist/ui/PanelDock.d.ts.map +1 -0
  210. package/dist/ui/PanelDock.js +297 -0
  211. package/dist/ui/PanelDock.js.map +1 -0
  212. package/dist/ui/Picker.d.ts +8 -2
  213. package/dist/ui/Picker.d.ts.map +1 -1
  214. package/dist/ui/Picker.js +86 -18
  215. package/dist/ui/Picker.js.map +1 -1
  216. package/dist/ui/SectionHead.d.ts +3 -3
  217. package/dist/ui/SectionHead.d.ts.map +1 -1
  218. package/dist/ui/SectionHead.js +4 -4
  219. package/dist/ui/SectionHead.js.map +1 -1
  220. package/dist/ui/Segmented.d.ts +2 -0
  221. package/dist/ui/Segmented.d.ts.map +1 -1
  222. package/dist/ui/Segmented.js +3 -1
  223. package/dist/ui/Segmented.js.map +1 -1
  224. package/dist/ui/Textarea.d.ts +2 -0
  225. package/dist/ui/Textarea.d.ts.map +1 -1
  226. package/dist/ui/Textarea.js +6 -1
  227. package/dist/ui/Textarea.js.map +1 -1
  228. package/dist/ui/Toast.d.ts +41 -8
  229. package/dist/ui/Toast.d.ts.map +1 -1
  230. package/dist/ui/Toast.js +216 -28
  231. package/dist/ui/Toast.js.map +1 -1
  232. package/dist/ui/WorkspacePicker.d.ts +15 -28
  233. package/dist/ui/WorkspacePicker.d.ts.map +1 -1
  234. package/dist/ui/WorkspacePicker.js +18 -27
  235. package/dist/ui/WorkspacePicker.js.map +1 -1
  236. package/dist/ui/card-css.d.ts +1 -1
  237. package/dist/ui/card-css.d.ts.map +1 -1
  238. package/dist/ui/card-css.generated.d.ts +2 -0
  239. package/dist/ui/card-css.generated.d.ts.map +1 -0
  240. package/dist/ui/card-css.generated.js +4 -0
  241. package/dist/ui/card-css.generated.js.map +1 -0
  242. package/dist/ui/card-css.js +1 -35
  243. package/dist/ui/card-css.js.map +1 -1
  244. package/dist/ui/chip-css.d.ts +1 -1
  245. package/dist/ui/chip-css.d.ts.map +1 -1
  246. package/dist/ui/chip-css.generated.d.ts +2 -0
  247. package/dist/ui/chip-css.generated.d.ts.map +1 -0
  248. package/dist/ui/chip-css.generated.js +4 -0
  249. package/dist/ui/chip-css.generated.js.map +1 -0
  250. package/dist/ui/chip-css.js +1 -17
  251. package/dist/ui/chip-css.js.map +1 -1
  252. package/dist/ui/code-viewer-css.d.ts +2 -0
  253. package/dist/ui/code-viewer-css.d.ts.map +1 -0
  254. package/dist/ui/code-viewer-css.generated.d.ts +2 -0
  255. package/dist/ui/code-viewer-css.generated.d.ts.map +1 -0
  256. package/dist/ui/code-viewer-css.generated.js +4 -0
  257. package/dist/ui/code-viewer-css.generated.js.map +1 -0
  258. package/dist/ui/code-viewer-css.js +3 -0
  259. package/dist/ui/code-viewer-css.js.map +1 -0
  260. package/dist/ui/code-viewer-lang.d.ts +15 -0
  261. package/dist/ui/code-viewer-lang.d.ts.map +1 -0
  262. package/dist/ui/code-viewer-lang.js +190 -0
  263. package/dist/ui/code-viewer-lang.js.map +1 -0
  264. package/dist/ui/code-viewer-theme.d.ts +5 -0
  265. package/dist/ui/code-viewer-theme.d.ts.map +1 -0
  266. package/dist/ui/code-viewer-theme.js +138 -0
  267. package/dist/ui/code-viewer-theme.js.map +1 -0
  268. package/dist/ui/controls/back-to-top-css.generated.d.ts +2 -0
  269. package/dist/ui/controls/back-to-top-css.generated.d.ts.map +1 -0
  270. package/dist/ui/controls/back-to-top-css.generated.js +4 -0
  271. package/dist/ui/controls/back-to-top-css.generated.js.map +1 -0
  272. package/dist/ui/controls/button-css.generated.d.ts +2 -0
  273. package/dist/ui/controls/button-css.generated.d.ts.map +1 -0
  274. package/dist/ui/controls/button-css.generated.js +4 -0
  275. package/dist/ui/controls/button-css.generated.js.map +1 -0
  276. package/dist/ui/controls/datetime-css.generated.d.ts +2 -0
  277. package/dist/ui/controls/datetime-css.generated.d.ts.map +1 -0
  278. package/dist/ui/controls/datetime-css.generated.js +4 -0
  279. package/dist/ui/controls/datetime-css.generated.js.map +1 -0
  280. package/dist/ui/controls/field-css.generated.d.ts +2 -0
  281. package/dist/ui/controls/field-css.generated.d.ts.map +1 -0
  282. package/dist/ui/controls/field-css.generated.js +4 -0
  283. package/dist/ui/controls/field-css.generated.js.map +1 -0
  284. package/dist/ui/controls/hint-css.generated.d.ts +2 -0
  285. package/dist/ui/controls/hint-css.generated.d.ts.map +1 -0
  286. package/dist/ui/controls/hint-css.generated.js +4 -0
  287. package/dist/ui/controls/hint-css.generated.js.map +1 -0
  288. package/dist/ui/controls/loading-css.generated.d.ts +2 -0
  289. package/dist/ui/controls/loading-css.generated.d.ts.map +1 -0
  290. package/dist/ui/controls/loading-css.generated.js +4 -0
  291. package/dist/ui/controls/loading-css.generated.js.map +1 -0
  292. package/dist/ui/controls/segmented-css.generated.d.ts +2 -0
  293. package/dist/ui/controls/segmented-css.generated.d.ts.map +1 -0
  294. package/dist/ui/controls/segmented-css.generated.js +4 -0
  295. package/dist/ui/controls/segmented-css.generated.js.map +1 -0
  296. package/dist/ui/controls-css.d.ts +7 -8
  297. package/dist/ui/controls-css.d.ts.map +1 -1
  298. package/dist/ui/controls-css.js +13 -11
  299. package/dist/ui/controls-css.js.map +1 -1
  300. package/dist/ui/css.d.ts +5 -0
  301. package/dist/ui/css.d.ts.map +1 -1
  302. package/dist/ui/css.js +13 -4
  303. package/dist/ui/css.js.map +1 -1
  304. package/dist/ui/datetime-logic.d.ts +100 -0
  305. package/dist/ui/datetime-logic.d.ts.map +1 -0
  306. package/dist/ui/datetime-logic.js +193 -0
  307. package/dist/ui/datetime-logic.js.map +1 -0
  308. package/dist/ui/feedback-css.d.ts +1 -1
  309. package/dist/ui/feedback-css.d.ts.map +1 -1
  310. package/dist/ui/feedback-css.generated.d.ts +2 -0
  311. package/dist/ui/feedback-css.generated.d.ts.map +1 -0
  312. package/dist/ui/feedback-css.generated.js +4 -0
  313. package/dist/ui/feedback-css.generated.js.map +1 -0
  314. package/dist/ui/feedback-css.js +1 -53
  315. package/dist/ui/feedback-css.js.map +1 -1
  316. package/dist/ui/host-data.d.ts +103 -0
  317. package/dist/ui/host-data.d.ts.map +1 -0
  318. package/dist/ui/host-data.js +106 -0
  319. package/dist/ui/host-data.js.map +1 -0
  320. package/dist/ui/host-toast.d.ts +23 -0
  321. package/dist/ui/host-toast.d.ts.map +1 -0
  322. package/dist/ui/host-toast.js +34 -0
  323. package/dist/ui/host-toast.js.map +1 -0
  324. package/dist/ui/index.d.ts +12 -6
  325. package/dist/ui/index.d.ts.map +1 -1
  326. package/dist/ui/index.js +10 -4
  327. package/dist/ui/index.js.map +1 -1
  328. package/dist/ui/marquee-css.d.ts +2 -0
  329. package/dist/ui/marquee-css.d.ts.map +1 -0
  330. package/dist/ui/marquee-css.generated.d.ts +2 -0
  331. package/dist/ui/marquee-css.generated.d.ts.map +1 -0
  332. package/dist/ui/marquee-css.generated.js +4 -0
  333. package/dist/ui/marquee-css.generated.js.map +1 -0
  334. package/dist/ui/marquee-css.js +4 -0
  335. package/dist/ui/marquee-css.js.map +1 -0
  336. package/dist/ui/modal-host.d.ts +30 -0
  337. package/dist/ui/modal-host.d.ts.map +1 -0
  338. package/dist/ui/modal-host.js +101 -0
  339. package/dist/ui/modal-host.js.map +1 -0
  340. package/dist/ui/official.d.ts.map +1 -1
  341. package/dist/ui/official.js +45 -1
  342. package/dist/ui/official.js.map +1 -1
  343. package/dist/ui/panel-dock-css.d.ts +2 -0
  344. package/dist/ui/panel-dock-css.d.ts.map +1 -0
  345. package/dist/ui/panel-dock-css.generated.d.ts +2 -0
  346. package/dist/ui/panel-dock-css.generated.d.ts.map +1 -0
  347. package/dist/ui/panel-dock-css.generated.js +4 -0
  348. package/dist/ui/panel-dock-css.generated.js.map +1 -0
  349. package/dist/ui/panel-dock-css.js +4 -0
  350. package/dist/ui/panel-dock-css.js.map +1 -0
  351. package/dist/ui/panel-dock-logic.d.ts +50 -0
  352. package/dist/ui/panel-dock-logic.d.ts.map +1 -0
  353. package/dist/ui/panel-dock-logic.js +64 -0
  354. package/dist/ui/panel-dock-logic.js.map +1 -0
  355. package/dist/ui/picker-css.d.ts +1 -1
  356. package/dist/ui/picker-css.d.ts.map +1 -1
  357. package/dist/ui/picker-css.generated.d.ts +2 -0
  358. package/dist/ui/picker-css.generated.d.ts.map +1 -0
  359. package/dist/ui/picker-css.generated.js +4 -0
  360. package/dist/ui/picker-css.generated.js.map +1 -0
  361. package/dist/ui/picker-css.js +1 -48
  362. package/dist/ui/picker-css.js.map +1 -1
  363. package/dist/ui/picker-icons.d.ts +12 -0
  364. package/dist/ui/picker-icons.d.ts.map +1 -0
  365. package/dist/ui/picker-icons.js +29 -0
  366. package/dist/ui/picker-icons.js.map +1 -0
  367. package/dist/ui/picker-logic.d.ts +4 -1
  368. package/dist/ui/picker-logic.d.ts.map +1 -1
  369. package/dist/ui/picker-logic.js +1 -2
  370. package/dist/ui/picker-logic.js.map +1 -1
  371. package/dist/ui/resizer.d.ts +3 -1
  372. package/dist/ui/resizer.d.ts.map +1 -1
  373. package/dist/ui/resizer.js +1 -1
  374. package/dist/ui/resizer.js.map +1 -1
  375. package/dist/ui/toast-host.d.ts +24 -0
  376. package/dist/ui/toast-host.d.ts.map +1 -0
  377. package/dist/ui/toast-host.js +20 -0
  378. package/dist/ui/toast-host.js.map +1 -0
  379. package/dist/utils/date.d.ts +8 -0
  380. package/dist/utils/date.d.ts.map +1 -1
  381. package/dist/utils/date.js +16 -0
  382. package/dist/utils/date.js.map +1 -1
  383. package/dist/utils/i18n.d.ts +1 -1
  384. package/dist/utils/i18n.d.ts.map +1 -1
  385. package/dist/utils/i18n.js +437 -18
  386. package/dist/utils/i18n.js.map +1 -1
  387. package/dist/utils/index.d.ts +1 -1
  388. package/dist/utils/index.d.ts.map +1 -1
  389. package/dist/utils/index.js +1 -1
  390. package/dist/utils/index.js.map +1 -1
  391. package/dist/utils/path.d.ts.map +1 -1
  392. package/dist/utils/path.js +1 -0
  393. package/dist/utils/path.js.map +1 -1
  394. package/docs/README.md +12 -5
  395. package/docs/design/architecture.md +38 -8
  396. package/docs/design/copywriting.md +95 -0
  397. package/docs/design/doc-format.md +80 -0
  398. package/docs/design/doc-format.ts +39 -0
  399. package/docs/design/external/dsh-host.md +150 -1
  400. package/docs/design/features.md +4 -17
  401. package/docs/design/methods.md +13 -34
  402. package/docs/design/structure.md +25 -22
  403. package/docs/design/style.md +24 -50
  404. package/docs/help/design.doc.ts +112 -0
  405. package/docs/help/design.md +88 -0
  406. package/docs/help/explorer.doc.ts +136 -0
  407. package/docs/help/explorer.md +68 -0
  408. package/docs/help/index.doc.ts +79 -0
  409. package/docs/help/index.md +28 -0
  410. package/docs/help/integration.doc.ts +114 -0
  411. package/docs/help/integration.md +127 -0
  412. package/docs/help/methods.md +58 -0
  413. package/docs/help/session.doc.ts +154 -0
  414. package/docs/help/session.md +91 -0
  415. package/docs/help/style.md +80 -0
  416. package/docs/help/ui.doc.ts +404 -0
  417. package/docs/help/ui.md +342 -0
  418. package/docs/help/utils.doc.ts +133 -0
  419. package/docs/help/utils.md +96 -0
  420. package/docs/requirements.md +33 -12
  421. package/package.json +44 -3
  422. package/dist/ui/ErrorBoundary.d.ts +0 -22
  423. package/dist/ui/ErrorBoundary.d.ts.map +0 -1
  424. package/dist/ui/ErrorBoundary.js +0 -30
  425. package/dist/ui/ErrorBoundary.js.map +0 -1
  426. package/docs/design/features/design.md +0 -55
  427. package/docs/design/features/explorer.md +0 -73
  428. package/docs/design/features/session.md +0 -70
  429. package/docs/design/features/ui.md +0 -225
  430. package/docs/design/features/utils.md +0 -64
  431. package/docs/examples/integration.md +0 -103
@@ -0,0 +1,659 @@
1
+ // 工作区文件浏览器(U11):面包屑 + ▾ 选层 + 内联展开目录树 + 文件预览。
2
+ //
3
+ // 源实现 = 兄弟项目 dsh-task-dispatch-table/src/client/file-browser.tsx(868 行)——本文件是它的
4
+ // core 重实现("抄"不是"复制"):组件全部换 core 自己的体系,官方件只经 ui/official 消费;
5
+ // 修掉源实现的已知问题:根缓存改可注入(原模块级 Map 永不清除)、复制路径补 catch、
6
+ // 复制/选中路径口径统一为工作区相对、去掉死代码。
7
+ //
8
+ // 两个消费场景共用本组件(用户 2026-10-20 拍板:同一套内容,两种展现形式):
9
+ // · 浏览(dock):由 **核心 PanelDock** 承载(openFilePreview),拖宽与关闭都由它负责,
10
+ // 本组件不再自绘拖拽条 / 侧边栏外壳;
11
+ // · 选择(picker):`picker` + `onPick(path, isDir)`(path 为**工作区相对**路径),点文件即回调。
12
+ //
13
+ // 控件纪律:能用核心控件的一律核心(ghost 面包屑 / IconButton / Segmented / MarqueeText);
14
+ // 核心没有的那一项 = ▾ 选层浮层,按兄弟项目 dsh-task-dispatch-table 的 `.dsh-tdt-sv-crumbs-*`
15
+ // 逐像素照抄(间距 / 圆角 / 最大高度 / 空态),不自创度量。
16
+ import { createElement as h, Fragment, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState, useSyncExternalStore, } from 'react';
17
+ import { IconCheckOutlineRegular, IconChevronDownOutlineRegular, IconChevronRightOutlineRegular, IconCloseOutlineRegular, IconCopyOutlineRegular, IconFolderCloseRegular, IconFolderOpenOutlineRegular, IconRefreshOutlineRegular, writeClipboard, FileTypeIcon, } from '../ui/official.js';
18
+ import { ensureControls } from '../ui/css.js';
19
+ import { Button, IconButton } from '../ui/Button.js';
20
+ import { MarqueeText } from '../ui/MarqueeText.js';
21
+ import { Segmented } from '../ui/Segmented.js';
22
+ import { workspaceList } from '../ui/host-data.js';
23
+ import { t } from '../utils/i18n.js';
24
+ import { FilePreview } from './preview/index.js';
25
+ import { absolutizeDir, bareCode, baseNameOfPath, crumbsOfDir, createRootCache, dirnameOf, errView, findAnyFileAbs, isAbsoluteish, isFailed, joinPath, learnRoot, listingOf, listPathOf, matchesFilter, relativizeToRoot, sortEntries, workspaceAnchorForPath, } from './types.js';
26
+ /**
27
+ * ▾ 下拉条目构造(**picker 与 dock 共用同一段代码**,差别只在入参——源实现用户 2026-09-29
28
+ * 点名提炼,严禁两处各写一份):
29
+ * - 当前工作区排第一(打开文件夹图标 + 加粗),**其下路径紧跟**(每层一个右箭头位缩进),
30
+ * 再列其他工作区(关合图标 + 灰)——「打开哪个就跟在哪个下面」;点当前工作区 = 回到其根目录。
31
+ * - 当前工作区未知(rootName 空或不在清单)时路径段置顶、全部工作区按「其他」罗列;
32
+ * - workspaces 不传 = 不显示工作区段(根无箭头、其下逐层缩进)。
33
+ *
34
+ * 条目是**自写浮层**(核心没有「带缩进的选择层菜单」这类控件 ⇒ 按兄弟项目
35
+ * `dsh-task-dispatch-table` 的 `.dsh-tdt-sv-crumbs-menu*` 逐条照抄间距):
36
+ * backdrop + 菜单本体 + `-item`(4px 8px / 最大宽 280 / 超出滚动 / 空态)。
37
+ */
38
+ function crumbsMenuEntries(params) {
39
+ const { workspaces, rootName, rootFallbackLabel, crumbs, onPickWorkspace, onLoadDir } = params;
40
+ const out = [];
41
+ // 内联样式照抄兄弟项目(wsEntry 的 gap 6px 覆盖类的 2px:图标与文字的间距以它为准)。
42
+ const wsEntry = (ws, current) => h('button', {
43
+ key: `ws:${ws}`,
44
+ type: 'button',
45
+ role: 'menuitem',
46
+ className: 'dshpc-fb__menu-item',
47
+ style: { paddingLeft: 8, display: 'flex', alignItems: 'center', gap: '6px' },
48
+ title: ws,
49
+ // 点当前工作区 = 回到该工作区根目录(浏览深处时唯一的「回根」入口,兄弟 2026-10-10);
50
+ // 点其他工作区才走 onPickWorkspace(换会话)。
51
+ onClick: () => {
52
+ if (current)
53
+ onLoadDir?.('');
54
+ else
55
+ onPickWorkspace?.(ws);
56
+ },
57
+ }, h('span', { className: 'dshpc-fb__menu-icon', style: { color: current ? 'var(--dshpc-fg)' : 'var(--dshpc-fg-2)' } }, h(current ? IconFolderOpenOutlineRegular : IconFolderCloseRegular, { size: 13 })), h('span', { className: 'dshpc-fb__menu-label', style: { fontWeight: current ? 600 : 400 } }, ws));
58
+ const pathEntry = (crumb, depth, withArrow = true) => h('button', {
59
+ key: `dir:${crumb.path}`,
60
+ type: 'button',
61
+ role: 'menuitem',
62
+ className: 'dshpc-fb__menu-item',
63
+ style: { paddingLeft: 8 },
64
+ title: crumb.path,
65
+ onClick: () => {
66
+ onLoadDir?.(crumb.path);
67
+ },
68
+ }, withArrow
69
+ ? h(Fragment, null, Array.from({ length: depth }, (_, s) => h('span', { key: `s${s}`, className: 'dshpc-fb__menu-chev-slot', 'aria-hidden': true })), h('span', { className: 'dshpc-fb__menu-chev' }, h(IconChevronRightOutlineRegular, { size: 11 })))
70
+ : null, h('span', { className: 'dshpc-fb__menu-label' }, crumb.label));
71
+ if (workspaces === undefined) {
72
+ if (crumbs.length === 0)
73
+ return [h('div', { key: 'empty', className: 'dshpc-fb__menu-empty' }, rootFallbackLabel)];
74
+ return crumbs.map((crumb, index) => pathEntry(crumb, index === 0 ? 0 : index - 1, index !== 0));
75
+ }
76
+ // 路径段:根 crumb(path='')已由工作区段表达时剔除,深度从根下一层起算。
77
+ const segments = rootName !== '' && crumbs.length > 0 && crumbs[0]?.path === '' ? crumbs.slice(1) : crumbs;
78
+ if (rootName !== '' && workspaces.includes(rootName)) {
79
+ // 当前工作区排第一,其下路径紧跟,然后是其他工作区(保持原相对顺序)。
80
+ out.push(wsEntry(rootName, true));
81
+ segments.forEach((crumb, i) => {
82
+ out.push(pathEntry(crumb, i));
83
+ });
84
+ for (const ws of workspaces) {
85
+ if (ws !== rootName)
86
+ out.push(wsEntry(ws, false));
87
+ }
88
+ }
89
+ else {
90
+ segments.forEach((crumb, i) => {
91
+ out.push(pathEntry(crumb, i));
92
+ });
93
+ for (const ws of workspaces)
94
+ out.push(wsEntry(ws, false));
95
+ }
96
+ return out;
97
+ }
98
+ /** 目录浏览器面板。详见 {@link FileBrowserProps}。 */
99
+ export function FileBrowser(props) {
100
+ ensureControls();
101
+ const tt = props.translate ?? t;
102
+ const picker = props.picker === true;
103
+ // 根缓存:调用方可注入(多实例/清理策略归调用方);不传则内部自建、随组件废弃。
104
+ const cacheRef = useRef(null);
105
+ if (cacheRef.current === null)
106
+ cacheRef.current = props.rootCache ?? createRootCache();
107
+ const rootCache = props.rootCache ?? cacheRef.current;
108
+ // mode:加载/目录树/文件预览/列举错误。viewing 非空 ⇒ 在 dir 树内预览文件。
109
+ const [mode, setMode] = useState('loading');
110
+ const [dir, setDir] = useState('');
111
+ const [listing, setListing] = useState(null);
112
+ const [truncated, setTruncated] = useState(false);
113
+ const [viewing, setViewing] = useState(null);
114
+ const [listErr, setListErr] = useState(null);
115
+ // 面包屑折叠(超宽时只显示当前层名;行首 ▾ 选层常驻)。
116
+ const [crumbsOverflow, setCrumbsOverflow] = useState(false);
117
+ const [menuOpen, setMenuOpen] = useState(false);
118
+ const regionRef = useRef(null);
119
+ const measureRef = useRef(null);
120
+ // 预览态:md/html 渲染⇄源码 + 刷新自增(触发预览体重读)。
121
+ const [sourceView, setSourceView] = useState(false);
122
+ const [reloadNonce, setReloadNonce] = useState(0);
123
+ const [copied, setCopied] = useState(false);
124
+ // 内联展开:openDirs = 已展开目录路径集合;childCache = 各展开目录拉到的子项。
125
+ const [openDirs, setOpenDirs] = useState(new Set());
126
+ const [childCache, setChildCache] = useState({});
127
+ // 工作区根补学完成信号(缓存非响应式,学成后 bump 触发面包屑重算)。
128
+ const [, setRootNonce] = useState(0);
129
+ // 当前目录在会话工作区之外(官方 list 限工作区内,越界即报 outside-workspace)。
130
+ // 依据 = list 的**真实错误码**,不靠缓存猜(根学不出时会误判成"在区内")。
131
+ const [outside, setOutside] = useState(false);
132
+ // 路径 → 工作区匹配:props.path 是绝对路径时,找出它所属的工作区(最长前缀),
133
+ // list / 学根 / 相对化**全部**换用该工作区的会话与根——官方 list 按 sessionId 解析工作区根,
134
+ // 只换 list 的 sessionId 不换学根的键,面包屑会露出工作区之外的层级(2026-10-22 真机:
135
+ // 匹配生效但 rootCache 仍按 props.sessionId 学根 ⇒ 相对化失败 ⇒ 显示 `C.x > workspace > …`)。
136
+ // 匹配不到 ⇒ 整体回落 props.sessionId(旧行为)。
137
+ // 工作区清单来源(优先级从高到低):① props.workspaceAnchors(调用方显式给,可覆盖);
138
+ // ② 宿主 workspaces 快照(connectHost 注入的 workspaceList,官方 WorkspaceView 镜像)。
139
+ // 快照异步到达时会重算 + 重跑初始 effect(listSessionId 在其依赖里)⇒ 自愈,无感。
140
+ const hostWorkspaces = useSyncExternalStore(workspaceList.subscribe, workspaceList.getSnapshot);
141
+ const anchors = props.workspaceAnchors ?? hostWorkspaces;
142
+ const anchorMatch = useMemo(() => workspaceAnchorForPath(props.path, anchors), [props.path, anchors]);
143
+ const listSessionId = anchorMatch?.sessionId ?? props.sessionId;
144
+ /** 记一次 list 结果的"是否越界"(outside-workspace / not-found 均视为不可浏览)。 */
145
+ const noteOutside = (parsed) => {
146
+ if (parsed === null || parsed === undefined)
147
+ return;
148
+ if (!isFailed(parsed)) {
149
+ setOutside(false);
150
+ return;
151
+ }
152
+ const code = bareCode(parsed.failed);
153
+ if (code === 'outside-workspace' || code === 'not-found')
154
+ setOutside(true);
155
+ };
156
+ /** 列举某目录并展示(清空 viewing;收起下拉)。 */
157
+ const fetchDir = useCallback((targetDir) => {
158
+ setDir(targetDir);
159
+ setViewing(null);
160
+ setListErr(null);
161
+ setMenuOpen(false);
162
+ setMode('loading');
163
+ // 切换顶层目录:清空内联展开态(展开树只属于当前这一层)。
164
+ setOpenDirs(new Set());
165
+ setChildCache({});
166
+ props.workspaceFiles
167
+ .list(listSessionId, listPathOf(targetDir))
168
+ .then((result) => {
169
+ const parsed = listingOf(result);
170
+ noteOutside(parsed);
171
+ if (isFailed(parsed)) {
172
+ setListErr(errView(parsed.failed));
173
+ setMode('error');
174
+ return;
175
+ }
176
+ if (parsed === null) {
177
+ setListErr({ key: 'previewBadPayload' });
178
+ setMode('error');
179
+ return;
180
+ }
181
+ setListing(parsed.entries);
182
+ setTruncated(parsed.truncated);
183
+ setMode('dir');
184
+ })
185
+ .catch((error) => {
186
+ setListErr(errView(error));
187
+ setMode('error');
188
+ });
189
+ }, [listSessionId, props.workspaceFiles]);
190
+ /** 进入某目录;点到当前目录本身 = 重列本层(刷新)。 */
191
+ const loadDir = useCallback((targetDir) => {
192
+ if (targetDir === dir) {
193
+ fetchDir(targetDir);
194
+ return;
195
+ }
196
+ fetchDir(targetDir);
197
+ }, [dir, fetchDir]);
198
+ // 初次进入(path 可能是文件或目录):
199
+ // list(path) 成功 ⇒ 目录树(dir 尽量取宿主绝对路径 ⇒ 面包屑从工作区根往下列);
200
+ // 报错 ⇒ 文件预览态(dir = 父目录,面包屑保留可返回)。
201
+ // ⚠️ 切勿改用服务端 list 返回的 path 当面包屑:那是 workspacePathOf 的工作区**相对**形式,
202
+ // 会丢掉根以下的前导段,面包屑只剩最近一层(源实现 2026-09-29 踩过 ⇒ 已回退为入参路径)。
203
+ useEffect(() => {
204
+ let alive = true;
205
+ setMode('loading');
206
+ setListErr(null);
207
+ setViewing(null);
208
+ setSourceView(false);
209
+ setReloadNonce(0);
210
+ setMenuOpen(false);
211
+ setOpenDirs(new Set());
212
+ setChildCache({});
213
+ /** 补学工作区根(面包屑根名显示 + picker 相对化要用):列目录 → 有文件就 stat 反推,没有就走有界 BFS。 */
214
+ const ensureRootLearned = (currentDir) => {
215
+ if (rootCache.get(listSessionId) !== undefined)
216
+ return;
217
+ void (async () => {
218
+ try {
219
+ const parsed = listingOf(await props.workspaceFiles.list(listSessionId, listPathOf(currentDir)));
220
+ if (!alive || parsed === null || isFailed(parsed))
221
+ return;
222
+ const stat = props.workspaceFiles.stat;
223
+ if (stat === undefined)
224
+ return;
225
+ const rel = parsed.path;
226
+ const file = parsed.entries.find((entry) => entry.type === 'file');
227
+ if (file !== undefined) {
228
+ const sub = rel === '' ? file.name : `${rel}/${file.name}`;
229
+ const abs = (await stat(listSessionId, sub).catch(() => null));
230
+ const absPath = typeof abs?.absolutePath === 'string' ? abs.absolutePath : null;
231
+ if (absPath !== null && learnRoot(rootCache, listSessionId, sub, absPath) !== null) {
232
+ setRootNonce((n) => n + 1);
233
+ return;
234
+ }
235
+ }
236
+ const found = await findAnyFileAbs(props.workspaceFiles, listSessionId, rel);
237
+ if (found !== null && learnRoot(rootCache, listSessionId, found.relativePath, found.absolutePath) !== null) {
238
+ setRootNonce((n) => n + 1);
239
+ }
240
+ }
241
+ catch {
242
+ /* 学不出就维持退化显示 */
243
+ }
244
+ })();
245
+ };
246
+ props.workspaceFiles
247
+ .list(listSessionId, listPathOf(props.path))
248
+ .then(async (result) => {
249
+ if (!alive)
250
+ return;
251
+ const parsed = listingOf(result);
252
+ if (!isFailed(parsed) && parsed !== null) {
253
+ setOutside(false);
254
+ // 入口可能是工作区相对名 ⇒ 用目录里任一文件子项的 stat 反推绝对路径;
255
+ // 解析不出(空目录/只有子目录/stat 缺失)就退回入参,不阻塞浏览。
256
+ const absDir = await absolutizeDir(rootCache, props.workspaceFiles, listSessionId, props.path, parsed.path, parsed.entries);
257
+ if (!alive)
258
+ return;
259
+ setDir(absDir);
260
+ setListing(parsed.entries);
261
+ setTruncated(parsed.truncated);
262
+ setMode('dir');
263
+ ensureRootLearned(absDir);
264
+ return;
265
+ }
266
+ // 不是目录 ⇒ 当作文件预览,dir 取父目录,尽量把父树也列出来。
267
+ let parent = dirnameOf(props.path);
268
+ if (!isAbsoluteish(props.path)) {
269
+ const stat = props.workspaceFiles.stat;
270
+ if (stat !== undefined) {
271
+ try {
272
+ const res = await stat(listSessionId, props.path);
273
+ const abs = typeof res.absolutePath === 'string'
274
+ ? res.absolutePath
275
+ : null;
276
+ if (abs !== null) {
277
+ parent = dirnameOf(abs);
278
+ // 记住工作区根 ⇒ 之后同会话里相对名也能解析
279
+ learnRoot(rootCache, listSessionId, props.path, abs);
280
+ }
281
+ }
282
+ catch {
283
+ /* 解析不出就用入参父目录 */
284
+ }
285
+ }
286
+ }
287
+ if (!alive)
288
+ return;
289
+ setDir(parent);
290
+ setViewing(props.path);
291
+ setMode('file');
292
+ ensureRootLearned(parent);
293
+ props.workspaceFiles
294
+ .list(listSessionId, listPathOf(parent))
295
+ .then((pres) => {
296
+ if (!alive)
297
+ return;
298
+ const pl = listingOf(pres);
299
+ noteOutside(pl);
300
+ if (!isFailed(pl) && pl !== null) {
301
+ setListing(pl.entries);
302
+ setTruncated(pl.truncated);
303
+ }
304
+ })
305
+ .catch(() => {
306
+ /* 父树列不出不影响文件预览 */
307
+ });
308
+ })
309
+ .catch(() => {
310
+ if (!alive)
311
+ return;
312
+ // 传输层失败:仍尝试按文件预览(预览体内部会给出错误态)。
313
+ const parent = dirnameOf(props.path);
314
+ setDir(parent);
315
+ setViewing(props.path);
316
+ setMode('file');
317
+ ensureRootLearned(parent);
318
+ });
319
+ return () => {
320
+ alive = false;
321
+ };
322
+ }, [props.workspaceFiles, props.path, rootCache, listSessionId]);
323
+ // 面包屑溢出测量:隐藏测量条渲染与可见态完全相同的 crumb 按钮(含 padding/max-width),
324
+ // 使溢出判定与真实排版一致——不超长时必定还原完整路径。ResizeObserver 同时覆盖
325
+ // dock 宽度变化 / 初次布局。
326
+ useLayoutEffect(() => {
327
+ const region = regionRef.current;
328
+ const measure = measureRef.current;
329
+ if (region === null || measure === null)
330
+ return;
331
+ const recompute = () => {
332
+ setCrumbsOverflow(measure.scrollWidth > region.clientWidth + 1);
333
+ };
334
+ recompute();
335
+ const ro = new ResizeObserver(recompute);
336
+ ro.observe(region);
337
+ return () => ro.disconnect();
338
+ }, [dir, viewing, mode, listing]);
339
+ const reload = useCallback(() => {
340
+ if (viewing !== null) {
341
+ setReloadNonce((n) => n + 1);
342
+ return;
343
+ }
344
+ loadDir(dir);
345
+ }, [viewing, dir, loadDir]);
346
+ const copyPath = useCallback(() => {
347
+ // 口径统一:复制**工作区相对**路径(与 picker onPick 一致;绝对形态对用户无意义)。
348
+ const target = viewing ?? dir;
349
+ if (target === '')
350
+ return;
351
+ const rel = relativizeToRoot(rootCache, listSessionId, target);
352
+ writeClipboard(rel)
353
+ .then((ok) => {
354
+ if (ok) {
355
+ setCopied(true);
356
+ window.setTimeout(() => setCopied(false), 1500);
357
+ }
358
+ })
359
+ .catch(() => {
360
+ /* 剪贴板不可用(非安全上下文等):静默,不弹错 */
361
+ });
362
+ }, [viewing, dir, rootCache, listSessionId]);
363
+ /** 内联展开/收起某目录(点 ▸):只切展开态,不导航;首次展开才拉子项。 */
364
+ const toggleDir = useCallback((path) => {
365
+ setOpenDirs((prev) => {
366
+ const next = new Set(prev);
367
+ if (next.has(path))
368
+ next.delete(path);
369
+ else
370
+ next.add(path);
371
+ return next;
372
+ });
373
+ if (!(path in childCache)) {
374
+ setChildCache((prev) => ({ ...prev, [path]: { status: 'loading' } }));
375
+ props.workspaceFiles
376
+ .list(listSessionId, listPathOf(path))
377
+ .then((result) => {
378
+ const parsed = listingOf(result);
379
+ setChildCache((prev) => ({
380
+ ...prev,
381
+ [path]: isFailed(parsed) || parsed === null
382
+ ? { status: 'error', error: errView(isFailed(parsed) ? parsed.failed : undefined) }
383
+ : { status: 'ready', entries: parsed.entries, truncated: parsed.truncated },
384
+ }));
385
+ })
386
+ .catch((error) => {
387
+ setChildCache((prev) => ({ ...prev, [path]: { status: 'error', error: errView(error) } }));
388
+ });
389
+ }
390
+ }, [childCache, props.workspaceFiles, listSessionId]);
391
+ // 过滤点名了扩展名 ⇒ 要的是**文件**:目录只作导航(点行就地展开),不给「选择」、也回传不了 isDir。
392
+ // (旧实现「目录永远保留且永远带选择钮」,于是「仅 JS/MD」下出现「文件夹旁边有选择、
393
+ // MD 文件旁边反而没有」,选中还回传一个文件夹——与过滤语义直接打架。)
394
+ const extsOnly = picker && props.filter !== undefined && props.filter.dirs !== true && (props.filter.exts?.length ?? 0) > 0;
395
+ /** 选择器里目录是否可选:不限 或 明说 dirs:true 才可选;扩展名过滤下不可选。 */
396
+ const dirPickable = picker && props.onPick !== undefined && !extsOnly;
397
+ /** 递归渲染目录树(内联展开)。file = 点开预览(picker = 选中);dir = ▸ 切展开、行尾钮分派。 */
398
+ const renderTree = useCallback((entries, baseDir) => sortEntries(entries).map((entry) => {
399
+ const childPath = joinPath(baseDir, entry.name);
400
+ const isDir = entry.type === 'directory';
401
+ // 选择器过滤:不匹配的文件不渲染(目录永远保留——里面可能有匹配的)。
402
+ if (!isDir && picker && !matchesFilter(childPath, false, props.filter))
403
+ return null;
404
+ if (!isDir) {
405
+ const pick = () => {
406
+ if (picker && props.onPick !== undefined) {
407
+ // 回传**工作区相对**路径(源实现真机 bug:绝对路径被宿主 zod 拒)。
408
+ props.onPick(relativizeToRoot(rootCache, listSessionId, childPath), false);
409
+ return;
410
+ }
411
+ // 逐层展开后选中文件:面包屑要跟随到该文件所在目录。
412
+ const parent = dirnameOf(childPath);
413
+ if (parent !== dir)
414
+ loadDir(parent);
415
+ setViewing(childPath);
416
+ setReloadNonce(0);
417
+ setSourceView(false);
418
+ };
419
+ return h('div', {
420
+ key: childPath,
421
+ className: `dshpc-fb__row${picker ? ' dshpc-fb__row--pick' : ''}`,
422
+ role: 'button',
423
+ tabIndex: 0,
424
+ title: picker ? tt('explorerPickFile') : childPath,
425
+ onClick: pick,
426
+ onKeyDown: (event) => {
427
+ if (event.key === 'Enter' || event.key === ' ')
428
+ pick();
429
+ },
430
+ }, h('span', { className: 'dshpc-fb__row-icon' }, h(FileTypeIcon, { path: childPath, size: 18 })), h('span', { className: 'dshpc-fb__row-name' }, entry.name),
431
+ // 选择器里文件行也给一枚「选择」钮,与目录行的操作位对齐(目录没有时它仍在,
432
+ // 「点行 = 选中」的旧默契保持不变,外显入口不再缺)。
433
+ picker && props.onPick !== undefined
434
+ ? h(Button, {
435
+ variant: 'outline',
436
+ size: 'sm',
437
+ className: 'dshpc-fb__row-act',
438
+ 'aria-label': tt('explorerPickFile'),
439
+ onClick: (event) => {
440
+ event.stopPropagation();
441
+ pick();
442
+ },
443
+ }, tt('explorerPickDir'))
444
+ : null);
445
+ }
446
+ const cached = childCache[childPath];
447
+ const isOpen = openDirs.has(childPath);
448
+ // 目录行点击 = 就地展开/收起(两种形态统一,源实现用户 2026-10-10 拍板);
449
+ // 主动作挪到行尾小按钮:选择器 = 选择此文件夹,浏览 = 进入该目录。
450
+ // 目录行不渲染文件夹图标——行首已有展开小尖号,再摆一个是重复。
451
+ const rowAction = () => {
452
+ toggleDir(childPath);
453
+ };
454
+ const actThisDir = (event) => {
455
+ event.stopPropagation();
456
+ if (picker) {
457
+ // 扩展名过滤下这里不该被触发(目录行根本不渲染这枚钮);兜住是为了语义不被绕过。
458
+ if (!extsOnly && props.onPick !== undefined)
459
+ props.onPick(relativizeToRoot(rootCache, listSessionId, childPath), true);
460
+ return;
461
+ }
462
+ loadDir(childPath);
463
+ };
464
+ return h(Fragment, { key: childPath }, h('div', {
465
+ className: 'dshpc-fb__row',
466
+ role: 'button',
467
+ tabIndex: 0,
468
+ title: childPath,
469
+ onClick: rowAction,
470
+ onKeyDown: (event) => {
471
+ if (event.key === 'Enter' || event.key === ' ')
472
+ rowAction();
473
+ },
474
+ },
475
+ // 展开 / 收起:核心 IconButton,20×20 命中位 + 展开时转 90°(与兄弟 .dsh-tdt-sv-tree-toggle 同款)。
476
+ h(IconButton, {
477
+ variant: 'plain',
478
+ size: 'sm',
479
+ className: `dshpc-fb__row-toggle${isOpen ? ' dshpc-fb__row-toggle--open' : ''}`,
480
+ icon: h(IconChevronRightOutlineRegular, { size: 16 }),
481
+ label: isOpen ? tt('explorerCollapse') : tt('explorerExpand'),
482
+ 'aria-expanded': isOpen,
483
+ onClick: (event) => {
484
+ event.stopPropagation();
485
+ toggleDir(childPath);
486
+ },
487
+ }), h('span', { className: 'dshpc-fb__row-name' }, entry.name),
488
+ // picker:仅目录可选时才出「选择」(扩展名过滤下没有,目录只作导航);
489
+ // 浏览态:出「进入」。
490
+ picker
491
+ ? dirPickable
492
+ ? h(Button, {
493
+ variant: 'outline',
494
+ size: 'sm',
495
+ className: 'dshpc-fb__row-act',
496
+ 'aria-label': tt('explorerPickDirAria'),
497
+ onClick: actThisDir,
498
+ }, tt('explorerPickDir'))
499
+ : null
500
+ : h(Button, {
501
+ variant: 'outline',
502
+ size: 'sm',
503
+ className: 'dshpc-fb__row-act',
504
+ 'aria-label': tt('explorerEnter'),
505
+ onClick: actThisDir,
506
+ }, tt('explorerEnter'))), isOpen
507
+ ? h('div', { className: 'dshpc-fb__row-children' },
508
+ // 硬性规定:不新建 Loading、不写加载文案 ⇒ 还在拉就空着(源实现用户 2026-10-05)。
509
+ cached === undefined || cached.status === 'loading'
510
+ ? null
511
+ : cached.status === 'error'
512
+ ? h('div', { className: 'dshpc-fb__row-err' }, tt(cached.error.key, cached.error.params))
513
+ : h(Fragment, null, renderTree(cached.entries, childPath), cached.truncated ? h('div', { className: 'dshpc-fb__row-note' }, tt('explorerTruncated')) : null))
514
+ : null);
515
+ }), [childCache, openDirs, picker, dirPickable, extsOnly, props.filter, props.onPick, listSessionId, rootCache, dir, loadDir, tt]);
516
+ // 面包屑 = 工作区根 + 其下相对层级。根名优先级:**匹配出的工作区名**(当前路径所属,
517
+ // 不写死)> 调用方 rootName > 缓存根末段。学根/相对化一律按 listSessionId——
518
+ // 用调用方原始 sessionId 学根会学出别的根 ⇒ 相对化失败 ⇒ 露出工作区外层级(真机 2026-10-22)。
519
+ const rootAbs = rootCache.get(listSessionId);
520
+ const rootLabel = anchorMatch?.title ?? props.rootName ?? (rootAbs !== undefined ? baseNameOfPath(rootAbs.replace(/\/+$/, '')) : '');
521
+ const crumbs = rootLabel !== '' ? [{ label: rootLabel, path: '' }, ...crumbsOfDir(relativizeToRoot(rootCache, listSessionId, dir))] : crumbsOfDir(dir);
522
+ // md / html 都出「渲染 ⇄ 源码」切换(默认渲染)。
523
+ const viewingIsMd = viewing !== null && /\.(md|markdown)$/i.test(viewing);
524
+ const viewingIsHtml = viewing !== null && /\.(html|htm)$/i.test(viewing);
525
+ const switchable = viewingIsMd || viewingIsHtml;
526
+ const menuItems = crumbsMenuEntries({
527
+ workspaces: props.workspaces,
528
+ rootName: rootLabel,
529
+ rootFallbackLabel: tt('explorerRootName'),
530
+ crumbs,
531
+ onPickWorkspace: props.onSelectWorkspace,
532
+ onLoadDir: loadDir,
533
+ });
534
+ /** 一段面包屑(核心 ghost 钮:无底无边;度量条与可见态必须逐字同构)。 */
535
+ const crumbButton = (label, onClick, current = false) => h(Button, {
536
+ variant: 'ghost',
537
+ size: 'sm',
538
+ className: `dshpc-fb__crumb${current ? ' dshpc-fb__crumb--current' : ''}`,
539
+ disabled: onClick === undefined,
540
+ tabIndex: onClick === undefined ? -1 : 0,
541
+ onClick,
542
+ }, h(MarqueeText, { text: label, className: 'dshpc-fb__crumb-mq' }));
543
+ const crumbBar = h('nav', { className: 'dshpc-fb__bar', 'aria-label': tt('explorerCrumbsAria') }, h('div', { className: 'dshpc-fb__menu-wrap' }, h(IconButton, {
544
+ variant: 'plain',
545
+ size: 'md',
546
+ icon: h(IconChevronDownOutlineRegular, { size: 14 }),
547
+ label: tt('explorerLevels'),
548
+ 'aria-expanded': menuOpen,
549
+ onClick: () => setMenuOpen((v) => !v),
550
+ }),
551
+ // 选层下拉 = 自写浮层(抄兄弟 .dsh-tdt-sv-crumbs-*):透明遮罩点一下即收,
552
+ // 遮罩层序高于 picker 面板(1100)⇒ 菜单开着时点面板也算「点外部」。
553
+ menuOpen
554
+ ? h(Fragment, null, h('div', {
555
+ className: 'dshpc-fb__crumbs-backdrop',
556
+ onClick: () => setMenuOpen(false),
557
+ }), h('div', { className: 'dshpc-fb__crumbs-menu', role: 'menu' }, menuItems))
558
+ : null), h('div', { ref: regionRef, className: 'dshpc-fb__crumbs' },
559
+ // 隐藏测量条:与可见态完全同构的 crumb 按钮,确保溢出判定精确。
560
+ h('span', { ref: measureRef, className: 'dshpc-fb__crumbs-measure', 'aria-hidden': true }, crumbs.length === 0
561
+ ? crumbButton(tt('explorerRootName'))
562
+ : crumbs.map((crumb, index) => h(Fragment, { key: crumb.path }, index > 0 ? h(IconChevronRightOutlineRegular, { className: 'dshpc-fb__crumb-sep', size: 12 }) : null, crumbButton(crumb.label)))),
563
+ // 工作区根目录(crumbs 空)也要有可见的面包屑占位。
564
+ crumbsOverflow
565
+ ? crumbButton(crumbs.length > 0 ? crumbs[crumbs.length - 1]?.label ?? tt('explorerRootName') : tt('explorerRootName'), undefined, true)
566
+ : crumbs.length === 0
567
+ ? crumbButton(tt('explorerRootName'), undefined, true)
568
+ : crumbs.map((crumb, index) => h(Fragment, { key: crumb.path }, index > 0 ? h(IconChevronRightOutlineRegular, { className: 'dshpc-fb__crumb-sep', size: 12 }) : null, crumbButton(crumb.label, () => loadDir(crumb.path))))), h('div', { className: 'dshpc-fb__actions' }, props.onClose === undefined
569
+ ? null
570
+ : h(IconButton, {
571
+ variant: 'plain',
572
+ size: 'md',
573
+ icon: h(IconCloseOutlineRegular, { size: 14 }),
574
+ label: tt('previewClose'),
575
+ onClick: props.onClose,
576
+ })));
577
+ // 越界(outside-workspace):第一排整条换成只读完整路径,不给任何会失败的入口。
578
+ const crumbBarPlain = h('nav', { className: 'dshpc-fb__bar', 'aria-label': tt('explorerCrumbsAria') }, h(MarqueeText, {
579
+ text: dir,
580
+ title: dir,
581
+ className: 'dshpc-fb__bar-plain',
582
+ style: { flex: '1 1 auto', minWidth: 0 },
583
+ }), h('div', { className: 'dshpc-fb__actions' }, props.onClose === undefined
584
+ ? null
585
+ : h(IconButton, {
586
+ variant: 'plain',
587
+ size: 'md',
588
+ icon: h(IconCloseOutlineRegular, { size: 14 }),
589
+ label: tt('previewClose'),
590
+ onClick: props.onClose,
591
+ })));
592
+ // 第二排(仅预览态显示):文件名 + 渲染⇄源码切换 / 复制路径 / 刷新。
593
+ // 档位照兄弟项目调用点:Segmented `sm` + 图标钮 `md`(核心 Segmented 高度由 CSS 定,不随档变)。
594
+ const titleBar = viewing === null
595
+ ? null
596
+ : h('div', { className: 'dshpc-fb__title' }, h(MarqueeText, {
597
+ text: baseNameOfPath(viewing),
598
+ title: viewing,
599
+ className: 'dshpc-fb__title-inner',
600
+ style: { flex: '1 1 auto', minWidth: 0 },
601
+ }), h('div', { className: 'dshpc-fb__actions' }, switchable
602
+ ? h(Segmented, {
603
+ size: 'sm',
604
+ variant: 'default',
605
+ label: viewingIsMd ? tt('previewMdSwitchAria') : tt('previewHtmlSwitchAria'),
606
+ value: sourceView ? 'source' : 'render',
607
+ items: [
608
+ { value: 'render', label: tt('previewRender') },
609
+ { value: 'source', label: tt('previewSource') },
610
+ ],
611
+ onChange: (next) => setSourceView(next === 'source'),
612
+ })
613
+ : null, h(IconButton, {
614
+ variant: 'plain',
615
+ size: 'md',
616
+ icon: copied ? h(IconCheckOutlineRegular, { size: 14 }) : h(IconCopyOutlineRegular, { size: 14 }),
617
+ label: tt('previewCopyPath'),
618
+ onClick: copyPath,
619
+ }), h(IconButton, {
620
+ variant: 'plain',
621
+ size: 'md',
622
+ icon: h(IconRefreshOutlineRegular, { size: 14 }),
623
+ label: tt('previewRefresh'),
624
+ onClick: reload,
625
+ })));
626
+ // ── 主体 ──
627
+ let body;
628
+ if (viewing !== null) {
629
+ body = h(FilePreview, {
630
+ key: `${viewing}:${reloadNonce}`,
631
+ workspaceFiles: props.workspaceFiles,
632
+ officeToPdf: props.officeToPdf ?? null,
633
+ sessionId: listSessionId,
634
+ path: viewing,
635
+ sourceView,
636
+ translate: tt,
637
+ });
638
+ }
639
+ else if (mode === 'error' && listErr !== null) {
640
+ // 列举失败(如 outside-workspace):只给错误文案;关闭(✕)即退出。
641
+ body = h('div', { className: 'dshpc-fb__body' }, h('div', { className: 'dshpc-fb__err' }, tt(listErr.key, listErr.params)));
642
+ }
643
+ else if (listing !== null) {
644
+ const visible = listing.filter((entry) => entry.type === 'directory' || matchesFilter(joinPath(dir, entry.name), false, picker ? props.filter : undefined));
645
+ body =
646
+ visible.length === 0
647
+ ? h('div', { className: 'dshpc-fb__body' }, h('div', { className: 'dshpc-fb__note' }, tt('explorerEmptyDir')))
648
+ : h('div', { className: 'dshpc-fb__tree' }, renderTree(visible, dir), truncated ? h('div', { className: 'dshpc-fb__row-note' }, tt('explorerTruncated')) : null);
649
+ }
650
+ else {
651
+ // 不动 Loading、不写加载文案 ⇒ 空着(源实现硬性规定)。
652
+ body = h('div', { className: 'dshpc-fb__body' });
653
+ }
654
+ return h('div', {
655
+ className: 'dshpc-fb',
656
+ style: props.style ?? undefined,
657
+ }, outside ? crumbBarPlain : crumbBar, titleBar, body);
658
+ }
659
+ //# sourceMappingURL=FileBrowser.js.map