@hienlh/ppm 0.17.57 → 0.18.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (600) hide show
  1. package/.release-run.sh +5 -0
  2. package/CHANGELOG.md +24 -0
  3. package/CLAUDE.md +4 -0
  4. package/assets/skills/ppm/SKILL.md +1 -1
  5. package/assets/skills/ppm/references/http-api.md +16 -2
  6. package/bun.lock +3 -0
  7. package/dist/web/assets/{ai-resource-editor-CXWQcx3_.js → ai-resource-editor-Bmk4P0YS.js} +1 -1
  8. package/dist/web/assets/{angular-html-D4YJUMLP.js → angular-html-C-Kjr43S.js} +1 -1
  9. package/dist/web/assets/{angular-ts-CUvq2h3X.js → angular-ts-CaDDbZqm.js} +1 -1
  10. package/dist/web/assets/api-client-CaRE4HYh.js +1 -0
  11. package/dist/web/assets/{api-client-COQtP-dB.js → api-client-rTAGdEKo.js} +1 -1
  12. package/dist/web/assets/{api-settings-Do0Z0IRN.js → api-settings-CAhcNpj5.js} +1 -1
  13. package/dist/web/assets/api-settings-DBcXfeJ8.js +1 -0
  14. package/dist/web/assets/{api-themes-DXi8sz-9.js → api-themes-CAjg_Bt9.js} +1 -1
  15. package/dist/web/assets/{apl-DSANFLx0.js → apl-B1WsQFAb.js} +1 -1
  16. package/dist/web/assets/architecture-PBZL5I3N-B4J2-O8Q.js +1 -0
  17. package/dist/web/assets/{astro-CXIotiNS.js → astro-Bdnz7nVp.js} +1 -1
  18. package/dist/web/assets/{audio-preview-D7jNc8mi.js → audio-preview-CikvnAOI.js} +1 -1
  19. package/dist/web/assets/{blade-BvrP2gPd.js → blade-B2euh8sS.js} +1 -1
  20. package/dist/web/assets/{bot-E9mcVZnr.js → bot-nk1k3ELu.js} +1 -1
  21. package/dist/web/assets/{bsl-CGf6Xuyu.js → bsl-GNeMaxd0.js} +1 -1
  22. package/dist/web/assets/{cairo-BboZ9qIf.js → cairo-D7G0W7-s.js} +1 -1
  23. package/dist/web/assets/can-open-in-ppm-BzVXoV-d.js +1 -0
  24. package/dist/web/assets/chat-tab-B3-KcCn2.js +13 -0
  25. package/dist/web/assets/chevron-right-BLOtX8Vy.js +1 -0
  26. package/dist/web/assets/{circle-question-mark-PaJgx-3d.js → circle-question-mark-CENpx4oA.js} +1 -1
  27. package/dist/web/assets/clock-D493FU_D.js +1 -0
  28. package/dist/web/assets/{cobol-D39V6ukp.js → cobol-Q6YgysnI.js} +1 -1
  29. package/dist/web/assets/code-CLF5x7KK.js +1 -0
  30. package/dist/web/assets/code-editor-BpbZw13T.js +10 -0
  31. package/dist/web/assets/{coffee-DTtK7kKi.js → coffee-BjufWxVc.js} +1 -1
  32. package/dist/web/assets/{conflict-editor-CpGcSopK.js → conflict-editor-DC3liBm_.js} +3 -3
  33. package/dist/web/assets/context-menu-q-RHHAWz.js +1 -0
  34. package/dist/web/assets/copy-BApI9v7Z.js +1 -0
  35. package/dist/web/assets/{cpp-CnU9hfBq.js → cpp-CqWU0gCR.js} +1 -1
  36. package/dist/web/assets/{createLucideIcon-ConhwJnb.js → createLucideIcon-D8pyde1A.js} +1 -1
  37. package/dist/web/assets/{crystal-DMjCL--0.js → crystal-ylayVajF.js} +1 -1
  38. package/dist/web/assets/csv-preview-BhCOjgq1.js +2 -0
  39. package/dist/web/assets/{data-grid-overlay-editor-Bdc80TJ1.js → data-grid-overlay-editor-BzPfsCfd.js} +1 -1
  40. package/dist/web/assets/{data-grid-types-BuMHLKXV.js → data-grid-types-CUx8cusN.js} +1 -1
  41. package/dist/web/assets/{database-COYAMZaw.js → database-B9okYLx6.js} +1 -1
  42. package/dist/web/assets/{database-viewer-DTMmic31.js → database-viewer-Z6uLyZVO.js} +1 -1
  43. package/dist/web/assets/dialog-CkI7rwrh.js +1 -0
  44. package/dist/web/assets/diff-viewer-CT1ALWt2.js +4 -0
  45. package/dist/web/assets/{dist-m_oJqIDk.js → dist-DduBIVkD.js} +1 -1
  46. package/dist/web/assets/{docx-preview-CR2ZtvNP.js → docx-preview-C_fSjfy_.js} +1 -1
  47. package/dist/web/assets/{edge-CTom35R_.js → edge-DX4NxQfh.js} +1 -1
  48. package/dist/web/assets/{edit-diff-preview-D1TEK7Jz.js → edit-diff-preview-DfX-9om9.js} +1 -1
  49. package/dist/web/assets/{elixir-BAX9HSOu.js → elixir-CSh3NjbV.js} +1 -1
  50. package/dist/web/assets/{elm-CpD28xsW.js → elm-DBzwFYq9.js} +1 -1
  51. package/dist/web/assets/{erb-DHX2IIEs.js → erb-yxVOb8aB.js} +1 -1
  52. package/dist/web/assets/{erlang-B_etLcPG.js → erlang-5XIDkYrM.js} +1 -1
  53. package/dist/web/assets/{esm-PmlN1RTs.js → esm-DO4el2OJ.js} +1 -1
  54. package/dist/web/assets/explorer-body-CQCyGEet.js +2 -0
  55. package/dist/web/assets/explorer-window-content-EtyTAZSh.js +1 -0
  56. package/dist/web/assets/{extension-webview-BTCFWY2A.js → extension-webview-ePIM2fwM.js} +1 -1
  57. package/dist/web/assets/{eye-off-Rq1n2-oe.js → eye-off-CUdzgmX8.js} +1 -1
  58. package/dist/web/assets/{file-exclamation-point-DBEC-Kst.js → file-exclamation-point-COAwgNGw.js} +1 -1
  59. package/dist/web/assets/{fortran-fixed-form-CpR0cN7O.js → fortran-fixed-form-D4tE5VWY.js} +1 -1
  60. package/dist/web/assets/{fsharp-DxITxZW5.js → fsharp-By8soj6-.js} +1 -1
  61. package/dist/web/assets/{gdresource-DJ7IvROZ.js → gdresource-DoSwM7Hv.js} +1 -1
  62. package/dist/web/assets/{git-commit-sQznNP43.js → git-commit-_ZiciHIx.js} +1 -1
  63. package/dist/web/assets/git-log-panel-BRWmTzX1.js +1 -0
  64. package/dist/web/assets/{git-rebase-DkHvejAR.js → git-rebase-C3Y5N9-s.js} +1 -1
  65. package/dist/web/assets/gitGraph-HDMCJU4V-CtQ3yXN-.js +1 -0
  66. package/dist/web/assets/glide-data-grid-DCJCz4XB.js +138 -0
  67. package/dist/web/assets/{glimmer-js-BwJnDfL-.js → glimmer-js-BPBTXVlC.js} +1 -1
  68. package/dist/web/assets/{glimmer-ts-Coz155XK.js → glimmer-ts-BQSZdy_D.js} +1 -1
  69. package/dist/web/assets/{glsl-BED7ZmUZ.js → glsl-CbQdxpU-.js} +1 -1
  70. package/dist/web/assets/{graphql-B_KyE6oz.js → graphql-GMlKikpY.js} +1 -1
  71. package/dist/web/assets/group-chat-tab-C3UD2bcm.js +1 -0
  72. package/dist/web/assets/{hack-sxywdIAQ.js → hack-DyshcLec.js} +1 -1
  73. package/dist/web/assets/{haml-Dts9JlPU.js → haml-rqCqWzsq.js} +1 -1
  74. package/dist/web/assets/{handlebars-C9HXIMtj.js → handlebars-BCKwSWjR.js} +1 -1
  75. package/dist/web/assets/{html-2p0RvXi4.js → html-Cg29xPR1.js} +1 -1
  76. package/dist/web/assets/{html-derivative-BiTPuOba.js → html-derivative-geltIVg8.js} +1 -1
  77. package/dist/web/assets/{http-CHd2gYPf.js → http-pG7Vp237.js} +1 -1
  78. package/dist/web/assets/{hurl-boMPgDm9.js → hurl-Di3Uu_Mc.js} +1 -1
  79. package/dist/web/assets/{hxml-BQvjiuBt.js → hxml-CRy4lbv8.js} +1 -1
  80. package/dist/web/assets/{image-preview-0SGb7_tH.js → image-preview-CP82lor8.js} +1 -1
  81. package/dist/web/assets/index-BYetJoXQ.js +52 -0
  82. package/dist/web/assets/index-D-xwjNyX.css +2 -0
  83. package/dist/web/assets/info-3K5VOQVL-Cg0mIJn9.js +1 -0
  84. package/dist/web/assets/{jinja-B-zKiwlp.js → jinja-C8GyVnvd.js} +1 -1
  85. package/dist/web/assets/{jison-C2vJYjbJ.js → jison-BywnqPn6.js} +1 -1
  86. package/dist/web/assets/{julia-DJ8MrQPA.js → julia-DTrO3T3B.js} +1 -1
  87. package/dist/web/assets/{just-BvQHq7VE.js → just-CA3KSHPi.js} +1 -1
  88. package/dist/web/assets/keybindings-store-yBWU8ZYT.js +1 -0
  89. package/dist/web/assets/{latex-ChNeshUC.js → latex-BC5xUMpc.js} +1 -1
  90. package/dist/web/assets/{lib-DTaN9riD.js → lib-BFetOULu.js} +1 -1
  91. package/dist/web/assets/{liquid-KNJEBOwW.js → liquid-Chd8tSyQ.js} +1 -1
  92. package/dist/web/assets/{lua-D8NNsLbC.js → lua-DHaEtwLv.js} +1 -1
  93. package/dist/web/assets/markdown-renderer-B2D4gdok.js +1 -0
  94. package/dist/web/assets/markdown-renderer-DDgl5zDc.js +3 -0
  95. package/dist/web/assets/{marko-HGo5Qtz4.js → marko-Desx_bC-.js} +1 -1
  96. package/dist/web/assets/{mdc-omkodQB5.js → mdc-DahWHc1t.js} +1 -1
  97. package/dist/web/assets/mobile-bottom-sheet-BQt45q9T.js +1 -0
  98. package/dist/web/assets/mobile-explorer-sheet-BtxyynR3.js +1 -0
  99. package/dist/web/assets/{nextflow-Adq02pv-.js → nextflow-3A7lutCA.js} +1 -1
  100. package/dist/web/assets/{nginx-ByvWruGD.js → nginx-XQda6Hdy.js} +1 -1
  101. package/dist/web/assets/{nim-BrMojX4O.js → nim-DHqlpwP1.js} +1 -1
  102. package/dist/web/assets/notification-store-DKw_mGED.js +1 -0
  103. package/dist/web/assets/{number-overlay-editor-CunvWJnN.js → number-overlay-editor-DgZtViPO.js} +1 -1
  104. package/dist/web/assets/packet-RMMSAZCW-D79vAFR_.js +1 -0
  105. package/dist/web/assets/{panel-store-CpKvXNnm.js → panel-store-s6Qx49RK.js} +1 -1
  106. package/dist/web/assets/{pdf-preview-DEn8amrO.js → pdf-preview-BXDOe7bG.js} +1 -1
  107. package/dist/web/assets/{perl-Bd_0l-b4.js → perl-M-ncjACb.js} +1 -1
  108. package/dist/web/assets/{php-D-DLTnWJ.js → php-CKIajrZi.js} +1 -1
  109. package/dist/web/assets/pie-UPGHQEXC-DYUOH68U.js +1 -0
  110. package/dist/web/assets/{plus-DcuJuDC3.js → plus-9LatwJMx.js} +1 -1
  111. package/dist/web/assets/{postgres-viewer-CjrM15gz.js → postgres-viewer-DkHYV33h.js} +3 -3
  112. package/dist/web/assets/{project-store-D0ALup9Z.js → project-store-DyaEpHVG.js} +1 -1
  113. package/dist/web/assets/{pug-D2aO-l2T.js → pug-DO0u_gO4.js} +1 -1
  114. package/dist/web/assets/{qml-CyQVzNXS.js → qml-UEje1PAA.js} +1 -1
  115. package/dist/web/assets/radar-KQ55EAFF-B1eznNtd.js +1 -0
  116. package/dist/web/assets/{razor-8tvJXsO3.js → razor-lCs5T1Ib.js} +1 -1
  117. package/dist/web/assets/{react-8hrD3-kv.js → react-w6wINGnd.js} +1 -1
  118. package/dist/web/assets/{rst-C4AZyQQl.js → rst-CZX_O0z4.js} +1 -1
  119. package/dist/web/assets/{ruby-O_z2NTLY.js → ruby-idycVAyE.js} +1 -1
  120. package/dist/web/assets/{sas-BtnF4zaV.js → sas-o5gTfUwp.js} +1 -1
  121. package/dist/web/assets/{save-BM4p9_9n.js → save-C4z1p51e.js} +1 -1
  122. package/dist/web/assets/{scss-GAyp5euH.js → scss-CRTk3iBQ.js} +1 -1
  123. package/dist/web/assets/settings-store-ChqHdT2V.js +2 -0
  124. package/dist/web/assets/settings-tab-ESL-6MAA.js +1 -0
  125. package/dist/web/assets/{shaderlab-nM5YZwa5.js → shaderlab-3e5ln8ci.js} +1 -1
  126. package/dist/web/assets/{shellsession-D2OCI4Gv.js → shellsession-CGQjQ75I.js} +1 -1
  127. package/dist/web/assets/{shield-check-C3qYSU8a.js → shield-check-C5laObJv.js} +1 -1
  128. package/dist/web/assets/{shield-off-D5tU7gQT.js → shield-off-DULFtyLS.js} +1 -1
  129. package/dist/web/assets/{soy-DrLNhqfp.js → soy-CxY0VwX2.js} +1 -1
  130. package/dist/web/assets/sparkles-n1hzh65o.js +1 -0
  131. package/dist/web/assets/{sparql-CsM6F2Yv.js → sparql-CBAGAFuq.js} +1 -1
  132. package/dist/web/assets/{sql-query-editor-CT5M9PKQ.js → sql-query-editor-CZdZuawP.js} +1 -1
  133. package/dist/web/assets/sqlite-viewer-Cpq06-nz.js +1 -0
  134. package/dist/web/assets/{stata-Bk3cgfXJ.js → stata-BoezhOvk.js} +1 -1
  135. package/dist/web/assets/{surrealql-Dkz0DPK8.js → surrealql-CHEzAhu7.js} +1 -1
  136. package/dist/web/assets/{svelte-23si1KV5.js → svelte-y6xtu2zX.js} +1 -1
  137. package/dist/web/assets/{system-monitor-tab-De3oz9zD.js → system-monitor-tab-XR8NXHpv.js} +1 -1
  138. package/dist/web/assets/{tab-store-BQmDVh9c.js → tab-store-C42sktPo.js} +1 -1
  139. package/dist/web/assets/{table-Di8pv2Y_.js → table-CHmxuh6M.js} +1 -1
  140. package/dist/web/assets/{templ-CPxlP4vF.js → templ-DbG2y5yD.js} +1 -1
  141. package/dist/web/assets/{terminal-tab-CciNqtMc.js → terminal-tab-CCCB-_50.js} +3 -3
  142. package/dist/web/assets/{tex-ugJpgYPc.js → tex-CeKQhrQG.js} +1 -1
  143. package/dist/web/assets/tool-cards-CsTs5go2.js +7 -0
  144. package/dist/web/assets/treemap-KZPCXAKY-SeI2TxLs.js +1 -0
  145. package/dist/web/assets/{ts-tags-BovP9TMu.js → ts-tags-iKKOXJjG.js} +1 -1
  146. package/dist/web/assets/{twig-B7VUm2Ca.js → twig-DK8Vrp-G.js} +1 -1
  147. package/dist/web/assets/{use-blob-url-B3YovXF6.js → use-blob-url-DYtOHK7u.js} +1 -1
  148. package/dist/web/assets/{use-is-mobile-BcuCjH19.js → use-is-mobile-DnFSkUG2.js} +1 -1
  149. package/dist/web/assets/use-monaco-theme-CZh7xTJZ.js +1 -0
  150. package/dist/web/assets/vendor-markdown-Ls5AcU91.js +291 -0
  151. package/dist/web/assets/{vendor-mermaid-CYOBtZtD.js → vendor-mermaid-C977xNeE.js} +1 -1
  152. package/dist/web/assets/{vendor-ui-DMRGWRuc.js → vendor-ui-CaeeFO0B.js} +2 -2
  153. package/dist/web/assets/{video-preview-D-S_YnG6.js → video-preview-KbRcyuAA.js} +1 -1
  154. package/dist/web/assets/{vue-m75pWowk.js → vue-JkIEObMV.js} +1 -1
  155. package/dist/web/assets/{vue-html-odHs7IMn.js → vue-html-D8SqnU86.js} +1 -1
  156. package/dist/web/assets/{vue-vine-BbBB3V_G.js → vue-vine-DJj7N4WD.js} +1 -1
  157. package/dist/web/assets/x-B1qHmLdR.js +1 -0
  158. package/dist/web/assets/{xml-BHzIcDWI.js → xml-C-00w9Rv.js} +1 -1
  159. package/dist/web/assets/{xsl-DTLhN7uu.js → xsl-CVdCwPHV.js} +1 -1
  160. package/dist/web/index.html +29 -26
  161. package/dist/web/monacoeditorwork/css.worker.bundle.js +122 -122
  162. package/dist/web/monacoeditorwork/editor.worker.bundle.js +78 -78
  163. package/dist/web/monacoeditorwork/html.worker.bundle.js +110 -110
  164. package/dist/web/monacoeditorwork/json.worker.bundle.js +108 -108
  165. package/dist/web/monacoeditorwork/ts.worker.bundle.js +81 -81
  166. package/dist/web/sw.js +1 -1
  167. package/docs/codebase-summary.md +10 -1
  168. package/docs/design-guidelines.md +31 -0
  169. package/docs/project-roadmap.md +10 -0
  170. package/docs/system-architecture.md +59 -0
  171. package/package.json +2 -1
  172. package/src/server/index.ts +8 -0
  173. package/src/server/routes/files.ts +2 -2
  174. package/src/server/routes/fs-browse.ts +99 -74
  175. package/src/server/routes/fs-ops.ts +118 -0
  176. package/src/server/routes/fs-sqlite.ts +129 -0
  177. package/src/server/routes/host-info.ts +17 -0
  178. package/src/server/routes/settings.ts +2 -0
  179. package/src/services/download-token.service.ts +21 -5
  180. package/src/services/file.service.ts +8 -12
  181. package/src/services/fs-browse.service.ts +104 -161
  182. package/src/services/fs-ops/fs-content-disposition.ts +17 -0
  183. package/src/services/fs-ops/fs-core-ops.ts +149 -0
  184. package/src/services/fs-ops/fs-error-response.ts +24 -0
  185. package/src/services/fs-ops/fs-git-init.service.ts +23 -0
  186. package/src/services/fs-ops/fs-hidden-names.ts +17 -0
  187. package/src/services/fs-ops/fs-list-files.service.ts +68 -0
  188. package/src/services/fs-ops/fs-ops-copy-move.service.ts +60 -0
  189. package/src/services/fs-ops/fs-ops-mutate.service.ts +59 -0
  190. package/src/services/fs-ops/fs-ops-read-write.service.ts +70 -0
  191. package/src/services/fs-ops/fs-ops-stat.service.ts +109 -0
  192. package/src/services/fs-ops/fs-ops-trash.service.ts +111 -0
  193. package/src/services/fs-ops/fs-real-path.ts +44 -0
  194. package/src/services/fs-ops/sql-row-reader.ts +26 -0
  195. package/src/services/fs-ops/sql-statement-guard.ts +63 -0
  196. package/src/services/fs-path-guard.service.ts +196 -0
  197. package/src/services/host-info/apple-bookmark-decoder.ts +97 -0
  198. package/src/services/host-info/apple-plist-xml-parser.ts +107 -0
  199. package/src/services/host-info/concurrency-limit.ts +20 -0
  200. package/src/services/host-info/host-drives.ts +190 -0
  201. package/src/services/host-info/host-info.service.ts +171 -0
  202. package/src/services/host-info/host-known-folders.ts +180 -0
  203. package/src/services/host-info/pinned-linux-bookmarks.ts +89 -0
  204. package/src/services/host-info/pinned-macos-finder-favorites.ts +175 -0
  205. package/src/services/host-info/pinned-windows-quick-access.ts +87 -0
  206. package/src/services/host-info/spawn-runner.ts +41 -0
  207. package/src/services/sqlite-types.ts +26 -0
  208. package/src/services/sqlite.service.ts +38 -29
  209. package/src/services/subagent-transcript-merger.ts +1 -1
  210. package/src/types/system.ts +50 -0
  211. package/src/web/app.tsx +19 -3
  212. package/src/web/components/editor/code-editor.tsx +3 -9
  213. package/src/web/components/explorer/file-tree.tsx +103 -21
  214. package/src/web/components/explorer/tree-node-context-menu.tsx +6 -1
  215. package/src/web/components/explorer/tree-node.tsx +34 -93
  216. package/src/web/components/explorer/use-file-upload-drag.ts +14 -9
  217. package/src/web/components/explorer/use-tree-row-dnd.ts +206 -0
  218. package/src/web/components/floating-window/default-window-chrome.tsx +71 -0
  219. package/src/web/components/floating-window/floating-window.tsx +167 -0
  220. package/src/web/components/floating-window/use-window-drag.ts +28 -0
  221. package/src/web/components/floating-window/use-window-gesture-context.ts +44 -0
  222. package/src/web/components/floating-window/use-window-keyboard.ts +55 -0
  223. package/src/web/components/floating-window/use-window-resize.ts +30 -0
  224. package/src/web/components/floating-window/window-chrome-contract.ts +38 -0
  225. package/src/web/components/floating-window/window-content-registry.ts +51 -0
  226. package/src/web/components/floating-window/window-geometry.ts +121 -0
  227. package/src/web/components/floating-window/window-layer.tsx +92 -0
  228. package/src/web/components/floating-window/window-persistence.ts +104 -0
  229. package/src/web/components/floating-window/window-resize-handles.tsx +81 -0
  230. package/src/web/components/floating-window/window-store-types.ts +20 -0
  231. package/src/web/components/floating-window/window-store.ts +192 -0
  232. package/src/web/components/group-chat/group-list.tsx +2 -3
  233. package/src/web/components/layout/command-palette.tsx +10 -0
  234. package/src/web/components/layout/mobile-drawer-tab-bar.tsx +3 -10
  235. package/src/web/components/layout/mobile-drawer.tsx +13 -2
  236. package/src/web/components/layout/nav-section-rail.tsx +16 -11
  237. package/src/web/components/os-explorer/actions/explorer-actions-clipboard.ts +186 -0
  238. package/src/web/components/os-explorer/actions/explorer-actions-mutate.ts +109 -0
  239. package/src/web/components/os-explorer/actions/explorer-actions-open.ts +67 -0
  240. package/src/web/components/os-explorer/actions/explorer-actions-transfer-helpers.ts +35 -0
  241. package/src/web/components/os-explorer/actions/use-explorer-actions.ts +205 -0
  242. package/src/web/components/os-explorer/can-open-in-ppm.ts +89 -0
  243. package/src/web/components/os-explorer/dnd/drag-depth-counter.ts +36 -0
  244. package/src/web/components/os-explorer/dnd/drag-ghost.ts +44 -0
  245. package/src/web/components/os-explorer/dnd/drop-target-decision.ts +46 -0
  246. package/src/web/components/os-explorer/dnd/drop-target-style.ts +7 -0
  247. package/src/web/components/os-explorer/dnd/entry-drag-payload.ts +115 -0
  248. package/src/web/components/os-explorer/dnd/entry-drag-state.ts +35 -0
  249. package/src/web/components/os-explorer/dnd/entry-drop-executor.ts +43 -0
  250. package/src/web/components/os-explorer/dnd/use-drag-auto-scroll.ts +70 -0
  251. package/src/web/components/os-explorer/dnd/use-drop-transfer.tsx +82 -0
  252. package/src/web/components/os-explorer/dnd/use-entry-drag-source.ts +73 -0
  253. package/src/web/components/os-explorer/dnd/use-entry-drop-target.ts +150 -0
  254. package/src/web/components/os-explorer/dnd/use-entry-row-dnd.ts +66 -0
  255. package/src/web/components/os-explorer/dnd/use-path-drop-target.ts +30 -0
  256. package/src/web/components/os-explorer/explorer-body.tsx +153 -0
  257. package/src/web/components/os-explorer/explorer-breadcrumb.tsx +108 -0
  258. package/src/web/components/os-explorer/explorer-context-menu.tsx +131 -0
  259. package/src/web/components/os-explorer/explorer-dialogs.tsx +103 -0
  260. package/src/web/components/os-explorer/explorer-modal-shell.tsx +60 -0
  261. package/src/web/components/os-explorer/explorer-pins-store.ts +63 -0
  262. package/src/web/components/os-explorer/explorer-sidebar.tsx +198 -0
  263. package/src/web/components/os-explorer/explorer-sort-menu.tsx +68 -0
  264. package/src/web/components/os-explorer/explorer-status-bar.tsx +35 -0
  265. package/src/web/components/os-explorer/explorer-store.ts +179 -0
  266. package/src/web/components/os-explorer/explorer-toolbar.tsx +139 -0
  267. package/src/web/components/os-explorer/explorer-window-content.tsx +36 -0
  268. package/src/web/components/os-explorer/format-file-meta.ts +74 -0
  269. package/src/web/components/os-explorer/icons/file-type-icon-map.ts +106 -0
  270. package/src/web/components/os-explorer/icons/file-type-icon.tsx +56 -0
  271. package/src/web/components/os-explorer/icons/thumbnail-fetch-semaphore.ts +44 -0
  272. package/src/web/components/os-explorer/icons/thumbnail-image.tsx +124 -0
  273. package/src/web/components/os-explorer/mobile/mobile-bottom-toolbar.tsx +102 -0
  274. package/src/web/components/os-explorer/mobile/mobile-explorer-sheet.tsx +61 -0
  275. package/src/web/components/os-explorer/mobile/mobile-explorer-top-bar.tsx +41 -0
  276. package/src/web/components/os-explorer/mobile/mobile-more-sheet.tsx +117 -0
  277. package/src/web/components/os-explorer/mobile/mobile-places-sheet.tsx +120 -0
  278. package/src/web/components/os-explorer/mobile/mobile-places-strip.tsx +109 -0
  279. package/src/web/components/os-explorer/mobile/mobile-tap-action.ts +19 -0
  280. package/src/web/components/os-explorer/mobile/use-mobile-row-tap.ts +50 -0
  281. package/src/web/components/os-explorer/open-explorer.ts +35 -0
  282. package/src/web/components/os-explorer/properties-dialog.tsx +99 -0
  283. package/src/web/components/os-explorer/skins/explorer-skin-chrome.tsx +17 -0
  284. package/src/web/components/os-explorer/skins/folder-icon-macos.tsx +42 -0
  285. package/src/web/components/os-explorer/skins/folder-icon-windows.tsx +25 -0
  286. package/src/web/components/os-explorer/skins/macos-skin.ts +14 -0
  287. package/src/web/components/os-explorer/skins/macos-window-chrome.tsx +69 -0
  288. package/src/web/components/os-explorer/skins/skin-types.ts +40 -0
  289. package/src/web/components/os-explorer/skins/skins.css +25 -0
  290. package/src/web/components/os-explorer/skins/use-explorer-skin.ts +21 -0
  291. package/src/web/components/os-explorer/skins/windows-skin.ts +11 -0
  292. package/src/web/components/os-explorer/skins/windows-window-chrome.tsx +56 -0
  293. package/src/web/components/os-explorer/sort-and-filter-entries.ts +52 -0
  294. package/src/web/components/os-explorer/sort-options.ts +29 -0
  295. package/src/web/components/os-explorer/toolbar-icon-button.ts +18 -0
  296. package/src/web/components/os-explorer/use-coarse-long-press.ts +97 -0
  297. package/src/web/components/os-explorer/use-explorer-keyboard.ts +124 -0
  298. package/src/web/components/os-explorer/use-explorer-navigation.ts +155 -0
  299. package/src/web/components/os-explorer/use-explorer-open-state.ts +67 -0
  300. package/src/web/components/os-explorer/use-host-info.ts +85 -0
  301. package/src/web/components/os-explorer/views/column-row.tsx +126 -0
  302. package/src/web/components/os-explorer/views/column-view-column.tsx +112 -0
  303. package/src/web/components/os-explorer/views/column-view-mobile.tsx +98 -0
  304. package/src/web/components/os-explorer/views/column-view-preview.tsx +70 -0
  305. package/src/web/components/os-explorer/views/column-view.tsx +204 -0
  306. package/src/web/components/os-explorer/views/compose-interactive-row-props.ts +77 -0
  307. package/src/web/components/os-explorer/views/explorer-view-registry.tsx +55 -0
  308. package/src/web/components/os-explorer/views/icons-view-tile.tsx +158 -0
  309. package/src/web/components/os-explorer/views/icons-view.tsx +188 -0
  310. package/src/web/components/os-explorer/views/inline-name-input.tsx +60 -0
  311. package/src/web/components/os-explorer/views/list-row.tsx +162 -0
  312. package/src/web/components/os-explorer/views/list-view.tsx +177 -0
  313. package/src/web/components/os-explorer/views/use-column-view-state.ts +158 -0
  314. package/src/web/components/os-explorer/views/use-entry-selection.ts +178 -0
  315. package/src/web/components/settings/settings-tab.tsx +29 -2
  316. package/src/web/components/sqlite/sqlite-viewer.tsx +5 -2
  317. package/src/web/components/sqlite/use-sqlite.ts +7 -2
  318. package/src/web/components/ui/adaptive-context-menu.tsx +57 -1
  319. package/src/web/components/ui/feature-badge.tsx +40 -0
  320. package/src/web/components/ui/file-browser-picker.tsx +1 -18
  321. package/src/web/lib/feature-badges.ts +22 -0
  322. package/src/web/lib/file-download.ts +6 -4
  323. package/src/web/lib/fs-api.ts +185 -0
  324. package/src/web/lib/sidebar-tabs/tab-registry.ts +4 -3
  325. package/src/web/stores/file-store.ts +38 -1
  326. package/src/web/stores/settings-store.ts +14 -0
  327. package/src/web/styles/globals.css +1 -0
  328. package/dist/web/assets/api-client-RtNXvS0P.js +0 -1
  329. package/dist/web/assets/api-settings-De--HNHp.js +0 -1
  330. package/dist/web/assets/architecture-PBZL5I3N-DVRYSsQn.js +0 -1
  331. package/dist/web/assets/chat-tab-C5U7a_rP.js +0 -13
  332. package/dist/web/assets/chevron-right-DeUue2aK.js +0 -1
  333. package/dist/web/assets/code-TekEnDFM.js +0 -1
  334. package/dist/web/assets/code-editor-CqlzLQ7T.js +0 -10
  335. package/dist/web/assets/context-menu-DIiZdfbE.js +0 -1
  336. package/dist/web/assets/csv-preview-DD94T9ff.js +0 -2
  337. package/dist/web/assets/dialog-HHdNInEH.js +0 -1
  338. package/dist/web/assets/diff-viewer-DyQLYP7J.js +0 -4
  339. package/dist/web/assets/git-log-panel-CrUgsLY5.js +0 -1
  340. package/dist/web/assets/gitGraph-HDMCJU4V-CutkUNY_.js +0 -1
  341. package/dist/web/assets/glide-data-grid-LinTYl0_.js +0 -138
  342. package/dist/web/assets/group-chat-tab-BqNJW7y2.js +0 -1
  343. package/dist/web/assets/index-CVJmlKhp.css +0 -2
  344. package/dist/web/assets/index-I2ik0ZF7.js +0 -50
  345. package/dist/web/assets/info-3K5VOQVL-BpNjgbj9.js +0 -1
  346. package/dist/web/assets/keybindings-store-C46tNxJE.js +0 -1
  347. package/dist/web/assets/markdown-renderer-DSxSupDq.js +0 -3
  348. package/dist/web/assets/markdown-renderer-xzyhJklS.js +0 -1
  349. package/dist/web/assets/notification-store-Dek7ClI2.js +0 -1
  350. package/dist/web/assets/packet-RMMSAZCW-D5IUZ66-.js +0 -1
  351. package/dist/web/assets/pie-UPGHQEXC-CM29eKDR.js +0 -1
  352. package/dist/web/assets/radar-KQ55EAFF-QtJGaSGt.js +0 -1
  353. package/dist/web/assets/settings-store-B3LfpCPa.js +0 -2
  354. package/dist/web/assets/settings-tab-DIuR1VIc.js +0 -1
  355. package/dist/web/assets/sparkles-B3DmG8PJ.js +0 -1
  356. package/dist/web/assets/sqlite-viewer-CEObRQ7n.js +0 -1
  357. package/dist/web/assets/tool-cards-Bdx04yYD.js +0 -7
  358. package/dist/web/assets/treemap-KZPCXAKY-CjUqpVnS.js +0 -1
  359. package/dist/web/assets/use-monaco-theme-k-17kQqf.js +0 -1
  360. package/dist/web/assets/vendor-markdown-CKTlmXbz.js +0 -291
  361. package/dist/web/assets/x-BsFLg-T8.js +0 -1
  362. /package/dist/web/assets/{abap-BM5PMK0-.js → abap-DrMyiWmK.js} +0 -0
  363. /package/dist/web/assets/{actionscript-3-CML-MTNy.js → actionscript-3-BlSOyi0y.js} +0 -0
  364. /package/dist/web/assets/{ada-DzO1tMqV.js → ada-B_m96icB.js} +0 -0
  365. /package/dist/web/assets/{andromeeda-C3nkvRhj.js → andromeeda-Ch3vOiZB.js} +0 -0
  366. /package/dist/web/assets/{apache-Dg7oWQbs.js → apache-CdsaXc1n.js} +0 -0
  367. /package/dist/web/assets/{apex-3O2170Ju.js → apex-0AnsBevk.js} +0 -0
  368. /package/dist/web/assets/{applescript-5AlzBqQO.js → applescript-CSxLolzy.js} +0 -0
  369. /package/dist/web/assets/{apply-theme-BSJDABU3.js → apply-theme-CMQXnUAa.js} +0 -0
  370. /package/dist/web/assets/{ara-BGtOX5Hn.js → ara-DXZS0jA5.js} +0 -0
  371. /package/dist/web/assets/{asciidoc-CIsC4kkq.js → asciidoc-DDy3pH2A.js} +0 -0
  372. /package/dist/web/assets/{asm-p1-PUkh3.js → asm-Bd17hhqg.js} +0 -0
  373. /package/dist/web/assets/{aurora-x-BPgGL50S.js → aurora-x-C62HJRs-.js} +0 -0
  374. /package/dist/web/assets/{awk-Cj93pRL8.js → awk-Cc-nazni.js} +0 -0
  375. /package/dist/web/assets/{ayu-dark-C50MYKhw.js → ayu-dark-BsfmNWCU.js} +0 -0
  376. /package/dist/web/assets/{ayu-light-DyIp0Idy.js → ayu-light-BZ4HLa4X.js} +0 -0
  377. /package/dist/web/assets/{ayu-mirage-BAdm8pKU.js → ayu-mirage-Bhyjyiqr.js} +0 -0
  378. /package/dist/web/assets/{ballerina-DUO9mwyV.js → ballerina-QiWgir3v.js} +0 -0
  379. /package/dist/web/assets/{bat-Cg8hlSct.js → bat-DxtlkwN3.js} +0 -0
  380. /package/dist/web/assets/{beancount-f8f3BBqB.js → beancount-Bt21X7M_.js} +0 -0
  381. /package/dist/web/assets/{berry-BqVQYZZr.js → berry-Cksre7lO.js} +0 -0
  382. /package/dist/web/assets/{bibtex-C_q8ygAM.js → bibtex-DkakgDlR.js} +0 -0
  383. /package/dist/web/assets/{bicep-DWS-2uWR.js → bicep-8crmcyXU.js} +0 -0
  384. /package/dist/web/assets/{bird2-C0pvipi_.js → bird2-CewQ2I_Z.js} +0 -0
  385. /package/dist/web/assets/{c-BQFvJ6Ux.js → c-C_6zE8Ha.js} +0 -0
  386. /package/dist/web/assets/{c3-Da53KeG6.js → c3-DLWB9-dp.js} +0 -0
  387. /package/dist/web/assets/{cadence-B5X2vWm3.js → cadence-D8qYS6pR.js} +0 -0
  388. /package/dist/web/assets/{catppuccin-frappe-Dm3rVY3b.js → catppuccin-frappe-Bh95lNRy.js} +0 -0
  389. /package/dist/web/assets/{catppuccin-latte-ZxS-ga_K.js → catppuccin-latte-C1PlN3G0.js} +0 -0
  390. /package/dist/web/assets/{catppuccin-macchiato-B0bAzXh0.js → catppuccin-macchiato-CldtgdK4.js} +0 -0
  391. /package/dist/web/assets/{catppuccin-mocha-BeMC5hqi.js → catppuccin-mocha-BiwqxX9A.js} +0 -0
  392. /package/dist/web/assets/{clarity-BRdirlsw.js → clarity-CGiU22jY.js} +0 -0
  393. /package/dist/web/assets/{clojure-pSLH-KQp.js → clojure-COIC3doh.js} +0 -0
  394. /package/dist/web/assets/{cmake-DsZu4U4F.js → cmake-DWUEQfHv.js} +0 -0
  395. /package/dist/web/assets/{codeowners-CtkKTnsH.js → codeowners-BNHiAQea.js} +0 -0
  396. /package/dist/web/assets/{codeql-BpP1PDrj.js → codeql-BuKaoS0j.js} +0 -0
  397. /package/dist/web/assets/{common-lisp-BX1XgHTt.js → common-lisp-D5IKbxsd.js} +0 -0
  398. /package/dist/web/assets/{coq-D2bX6-8g.js → coq-BMVS-p94.js} +0 -0
  399. /package/dist/web/assets/{csharp-DcR97P0D.js → csharp-DMlbXbM4.js} +0 -0
  400. /package/dist/web/assets/{css-CIjciIIk.js → css-CjkJC89X.js} +0 -0
  401. /package/dist/web/assets/{csv-DW48Z5d-.js → csv-DoNVBBf0.js} +0 -0
  402. /package/dist/web/assets/{csv-parser-DVHBcvuE.js → csv-parser-DHvoTjMF.js} +0 -0
  403. /package/dist/web/assets/{cue-Byh1xHko.js → cue-DoTRbBg-.js} +0 -0
  404. /package/dist/web/assets/{cypher-TVlMMWma.js → cypher-DVsNdTT3.js} +0 -0
  405. /package/dist/web/assets/{d-CxaScvxf.js → d-EX7BBSrv.js} +0 -0
  406. /package/dist/web/assets/{dark-plus-sn-FFTT1.js → dark-plus-P_YTHwlh.js} +0 -0
  407. /package/dist/web/assets/{dart-BmpakMe-.js → dart-Do-rgU4S.js} +0 -0
  408. /package/dist/web/assets/{dax-B1aRUMXT.js → dax-DxOieacu.js} +0 -0
  409. /package/dist/web/assets/{desktop-C6lD62ar.js → desktop-CvdV7SBf.js} +0 -0
  410. /package/dist/web/assets/{diff-CupGmT1a.js → diff-CNOetGen.js} +0 -0
  411. /package/dist/web/assets/{dist-Bi4gRyhr.js → dist-CMfLpPW_.js} +0 -0
  412. /package/dist/web/assets/{docker-DjDr3TJF.js → docker-DAlG4_q-.js} +0 -0
  413. /package/dist/web/assets/{dotenv-QeT1SLTv.js → dotenv-Dh3qf6yx.js} +0 -0
  414. /package/dist/web/assets/{dracula-yI5kpKp5.js → dracula-baAGmJYG.js} +0 -0
  415. /package/dist/web/assets/{dracula-soft-CYF6cJce.js → dracula-soft-l7ZIyums.js} +0 -0
  416. /package/dist/web/assets/{dream-maker-TBDKiHrV.js → dream-maker-DeRjdBn8.js} +0 -0
  417. /package/dist/web/assets/{emacs-lisp-B7aZTnJ_.js → emacs-lisp-CB05-jQA.js} +0 -0
  418. /package/dist/web/assets/{everforest-dark-CN77B1NJ.js → everforest-dark-CT-llQBT.js} +0 -0
  419. /package/dist/web/assets/{everforest-light-CyFxGMIs.js → everforest-light-ByPJkTT7.js} +0 -0
  420. /package/dist/web/assets/{fennel-C6ktGUzp.js → fennel-CeMarbvn.js} +0 -0
  421. /package/dist/web/assets/{fish-Vr62C2vP.js → fish-BYrt6Xtb.js} +0 -0
  422. /package/dist/web/assets/{fluent-CH3IJUki.js → fluent-Cr5VcAwh.js} +0 -0
  423. /package/dist/web/assets/{fortran-free-form-BN7VmmxZ.js → fortran-free-form-DQmKtrLa.js} +0 -0
  424. /package/dist/web/assets/{gdscript-BYdRNu_P.js → gdscript-QTDKjzhY.js} +0 -0
  425. /package/dist/web/assets/{gdshader-C2XOq90k.js → gdshader-Chr-5UYt.js} +0 -0
  426. /package/dist/web/assets/{genie-B4hkIXNU.js → genie-kWHMWnt0.js} +0 -0
  427. /package/dist/web/assets/{gherkin-CW9NH2DW.js → gherkin-DtEBQFUo.js} +0 -0
  428. /package/dist/web/assets/{github-dark-BWCf99kM.js → github-dark-B5aiUta2.js} +0 -0
  429. /package/dist/web/assets/{github-dark-default-DZ1m_6OP.js → github-dark-default-BkxtsTqR.js} +0 -0
  430. /package/dist/web/assets/{github-dark-dimmed-CUXSQ8bS.js → github-dark-dimmed-B9QjR_0K.js} +0 -0
  431. /package/dist/web/assets/{github-dark-high-contrast-B6BvU8H-.js → github-dark-high-contrast-D6bO-5c0.js} +0 -0
  432. /package/dist/web/assets/{github-light-Ch-E92cy.js → github-light-Cg2ZW_CJ.js} +0 -0
  433. /package/dist/web/assets/{github-light-default-CKFslV7i.js → github-light-default-eD7qUVlQ.js} +0 -0
  434. /package/dist/web/assets/{github-light-high-contrast-DiJVeRlZ.js → github-light-high-contrast-CFnlSVjd.js} +0 -0
  435. /package/dist/web/assets/{gleam-D4dP7V5M.js → gleam-BpYoOqIT.js} +0 -0
  436. /package/dist/web/assets/{gn-DuO2D2eW.js → gn-BxwtZPau.js} +0 -0
  437. /package/dist/web/assets/{gnuplot-Df_8pFbI.js → gnuplot-CRyiZDfl.js} +0 -0
  438. /package/dist/web/assets/{go-BL16cMJO.js → go-Dw1Qx94W.js} +0 -0
  439. /package/dist/web/assets/{groovy-rfHeCRqy.js → groovy-zq_SbWk-.js} +0 -0
  440. /package/dist/web/assets/{gruvbox-dark-hard-CLbDN-E3.js → gruvbox-dark-hard-DbbNy8-Q.js} +0 -0
  441. /package/dist/web/assets/{gruvbox-dark-medium-Df0L0qje.js → gruvbox-dark-medium-BQZ7Kj6C.js} +0 -0
  442. /package/dist/web/assets/{gruvbox-dark-soft-DV6TAcen.js → gruvbox-dark-soft-vNavErXi.js} +0 -0
  443. /package/dist/web/assets/{gruvbox-light-hard-CWXUzp9b.js → gruvbox-light-hard-AOFbCd7i.js} +0 -0
  444. /package/dist/web/assets/{gruvbox-light-medium-BOHMe1-7.js → gruvbox-light-medium-DqtxND6H.js} +0 -0
  445. /package/dist/web/assets/{gruvbox-light-soft-DrrS2sdV.js → gruvbox-light-soft-Cg0basu6.js} +0 -0
  446. /package/dist/web/assets/{haskell-DybKb9uW.js → haskell-CcsmcOez.js} +0 -0
  447. /package/dist/web/assets/{haxe-DLRwZxmt.js → haxe-BimYY9X4.js} +0 -0
  448. /package/dist/web/assets/{hcl-CusCzwOk.js → hcl-CTrXCK40.js} +0 -0
  449. /package/dist/web/assets/{hjson-BygWIJ-3.js → hjson-CmqqU6Qg.js} +0 -0
  450. /package/dist/web/assets/{hlsl-DCKvuEyZ.js → hlsl-CuJtX_uf.js} +0 -0
  451. /package/dist/web/assets/{horizon-DSOVAzyH.js → horizon-BGeSjDYJ.js} +0 -0
  452. /package/dist/web/assets/{horizon-bright-DKfVjGj_.js → horizon-bright-GYMgd3R0.js} +0 -0
  453. /package/dist/web/assets/{houston-Ddm8AgpV.js → houston--JD_5r2q.js} +0 -0
  454. /package/dist/web/assets/{hy-DzZa6alE.js → hy-C9ILOiqk.js} +0 -0
  455. /package/dist/web/assets/{image-gallery-CObzTisL.js → image-gallery-BWFpZAAP.js} +0 -0
  456. /package/dist/web/assets/{imba-aiXalPnK.js → imba-B6F3yus5.js} +0 -0
  457. /package/dist/web/assets/{ini-CAvrVa5R.js → ini-BfkQswMZ.js} +0 -0
  458. /package/dist/web/assets/{java-PRMSQp24.js → java-DEH5avQ1.js} +0 -0
  459. /package/dist/web/assets/{javascript-DQR6GQKs.js → javascript-Dr4yHuV2.js} +0 -0
  460. /package/dist/web/assets/{json-uWUKqOxq.js → json-BuR35ewf.js} +0 -0
  461. /package/dist/web/assets/{json5-R_LXJXL0.js → json5-Ny9ZiJAC.js} +0 -0
  462. /package/dist/web/assets/{jsonc-tC5zvrPO.js → jsonc-zYVuoZkR.js} +0 -0
  463. /package/dist/web/assets/{jsonl-BAwnWh7U.js → jsonl-B9xthb_H.js} +0 -0
  464. /package/dist/web/assets/{jsonnet-CPj4HCRm.js → jsonnet-CCoLJbMP.js} +0 -0
  465. /package/dist/web/assets/{jssm-B7HswxOM.js → jssm-W0GDlQXi.js} +0 -0
  466. /package/dist/web/assets/{jsx-z4TGELE1.js → jsx-BrLJpWC-.js} +0 -0
  467. /package/dist/web/assets/{kanagawa-dragon-BpeLlraV.js → kanagawa-dragon-CuVwt_MO.js} +0 -0
  468. /package/dist/web/assets/{kanagawa-lotus-CLnIPAGs.js → kanagawa-lotus-B3W_617P.js} +0 -0
  469. /package/dist/web/assets/{kanagawa-wave-BglPniBb.js → kanagawa-wave-CEx4MP5W.js} +0 -0
  470. /package/dist/web/assets/{kdl-B6blIqLq.js → kdl-DilRejnB.js} +0 -0
  471. /package/dist/web/assets/{kotlin-DVAEYiwY.js → kotlin-Bq5JtKaa.js} +0 -0
  472. /package/dist/web/assets/{kusto-Ba87977j.js → kusto-Bhp2KYog.js} +0 -0
  473. /package/dist/web/assets/{laserwave-C-NuzoMp.js → laserwave-WA_7c5hu.js} +0 -0
  474. /package/dist/web/assets/{lean-CJ_KLkrJ.js → lean-AEGcXwS-.js} +0 -0
  475. /package/dist/web/assets/{less-Dfn9YC_2.js → less-NPqH-26u.js} +0 -0
  476. /package/dist/web/assets/{libesm-DdtEjhIi.js → libesm-tR4XlhMj.js} +0 -0
  477. /package/dist/web/assets/{light-plus-B3BLlguG.js → light-plus-B4xW7cgY.js} +0 -0
  478. /package/dist/web/assets/{llvm-6UDP3NQb.js → llvm-CPyWNcDE.js} +0 -0
  479. /package/dist/web/assets/{log-QW3dqr1D.js → log-CeQmiQSz.js} +0 -0
  480. /package/dist/web/assets/{logo-DUinJheI.js → logo-BO0VrjBm.js} +0 -0
  481. /package/dist/web/assets/{luau-B1vcBzl8.js → luau-B6GT9kA1.js} +0 -0
  482. /package/dist/web/assets/{make-CqNL10gS.js → make-CwfmN7e_.js} +0 -0
  483. /package/dist/web/assets/{markdown-BQNMNiYS.js → markdown-Bbe4FlLp.js} +0 -0
  484. /package/dist/web/assets/{material-theme-darker-BZrskvoo.js → material-theme-darker-u7M3XGe7.js} +0 -0
  485. /package/dist/web/assets/{material-theme-rbV8EefR.js → material-theme-iD9XbfsB.js} +0 -0
  486. /package/dist/web/assets/{material-theme-lighter-B0CBBjBw.js → material-theme-lighter-BGdI48zn.js} +0 -0
  487. /package/dist/web/assets/{material-theme-ocean-CX_CHnQq.js → material-theme-ocean-_mk62F5q.js} +0 -0
  488. /package/dist/web/assets/{material-theme-palenight-ztiOCPbw.js → material-theme-palenight-CxFbDyAu.js} +0 -0
  489. /package/dist/web/assets/{matlab-tHQDNC9G.js → matlab-Z0RUE3V_.js} +0 -0
  490. /package/dist/web/assets/{mdx-D4kZ6c6G.js → mdx-BZ5wPYzV.js} +0 -0
  491. /package/dist/web/assets/{mermaid-DlR4U4Pe.js → mermaid-CY1_aP-h.js} +0 -0
  492. /package/dist/web/assets/{min-dark-BX-xHAD2.js → min-dark-DKWtxOre.js} +0 -0
  493. /package/dist/web/assets/{min-light-Bxw0_Gqq.js → min-light-e1iwHDfP.js} +0 -0
  494. /package/dist/web/assets/{mipsasm-DYyZAum-.js → mipsasm-BiDfQ4ir.js} +0 -0
  495. /package/dist/web/assets/{mojo-q9wuEYKR.js → mojo-DteFEHsj.js} +0 -0
  496. /package/dist/web/assets/{monokai-D9vrJ8JM.js → monokai-BgPbE9xZ.js} +0 -0
  497. /package/dist/web/assets/{moonbit-C9roWxMb.js → moonbit-mEbRp-mA.js} +0 -0
  498. /package/dist/web/assets/{move-BvhjG2ic.js → move-CogqZw7A.js} +0 -0
  499. /package/dist/web/assets/{narrat-BXGbPwG3.js → narrat-BD2qjmy1.js} +0 -0
  500. /package/dist/web/assets/{nextflow-groovy-CMy5-Z4k.js → nextflow-groovy-BNX8GOD_.js} +0 -0
  501. /package/dist/web/assets/{night-owl-CBQBcbmw.js → night-owl-ed3GbziD.js} +0 -0
  502. /package/dist/web/assets/{night-owl-light-CC-brflp.js → night-owl-light-B0j7O0Wn.js} +0 -0
  503. /package/dist/web/assets/{nix-B9EAdptu.js → nix-DFDbcQQm.js} +0 -0
  504. /package/dist/web/assets/{nord-DxASd4qG.js → nord-D93TxEQi.js} +0 -0
  505. /package/dist/web/assets/{nushell-BsY59i7N.js → nushell-3_H_XKja.js} +0 -0
  506. /package/dist/web/assets/{objective-c-CoeQAcnP.js → objective-c-BM3u6nlm.js} +0 -0
  507. /package/dist/web/assets/{objective-cpp-BysdFvND.js → objective-cpp-DZ73h42g.js} +0 -0
  508. /package/dist/web/assets/{ocaml-CrtQYMMK.js → ocaml-B1PU5gmh.js} +0 -0
  509. /package/dist/web/assets/{odin-B8pz4gIL.js → odin-D14L6aRL.js} +0 -0
  510. /package/dist/web/assets/{one-dark-pro-3sSHqoqQ.js → one-dark-pro-Bj-94Z8v.js} +0 -0
  511. /package/dist/web/assets/{one-light-LUZAvT8g.js → one-light-DTdGWyOZ.js} +0 -0
  512. /package/dist/web/assets/{openscad-DcKia-sV.js → openscad-Ciq554Sj.js} +0 -0
  513. /package/dist/web/assets/{pascal-zM5SlmgF.js → pascal-Bfd4qdGi.js} +0 -0
  514. /package/dist/web/assets/{pkl-C_r_zLLt.js → pkl-CTurDUfj.js} +0 -0
  515. /package/dist/web/assets/{plastic-B3cRtgKD.js → plastic-BLQfZXQp.js} +0 -0
  516. /package/dist/web/assets/{plsql-BzyjheXU.js → plsql-DyYfP9kQ.js} +0 -0
  517. /package/dist/web/assets/{po-Dz4OaDNi.js → po-CgXdT8vQ.js} +0 -0
  518. /package/dist/web/assets/{poimandres-BBbtYwmR.js → poimandres-DOg5fK6s.js} +0 -0
  519. /package/dist/web/assets/{polar-Che1XC2Z.js → polar-Dv4aoL6X.js} +0 -0
  520. /package/dist/web/assets/{postcss-DouzwG4F.js → postcss-DxugHnJD.js} +0 -0
  521. /package/dist/web/assets/{powerquery-YOdcTZmd.js → powerquery-CR3kzRyX.js} +0 -0
  522. /package/dist/web/assets/{powershell-8ojzYH34.js → powershell-BE91xJQB.js} +0 -0
  523. /package/dist/web/assets/{prisma-DCmjceML.js → prisma-B_3yUlRQ.js} +0 -0
  524. /package/dist/web/assets/{prolog-ByNNz2pB.js → prolog-DcT781Ht.js} +0 -0
  525. /package/dist/web/assets/{proto-DWMt6Qu1.js → proto-CSf-w5k2.js} +0 -0
  526. /package/dist/web/assets/{puppet-osfKyZp4.js → puppet-CLGO6QWl.js} +0 -0
  527. /package/dist/web/assets/{purescript-ClIblkvh.js → purescript-Bah2McKd.js} +0 -0
  528. /package/dist/web/assets/{python-Ctyr4faP.js → python-DUH8qy7N.js} +0 -0
  529. /package/dist/web/assets/{qmldir-CbNgyhnI.js → qmldir-YIsHnjKq.js} +0 -0
  530. /package/dist/web/assets/{qss-LbRHzb21.js → qss-CLmoVNA4.js} +0 -0
  531. /package/dist/web/assets/{r-Dvfjp0wc.js → r-Pon-b-vz.js} +0 -0
  532. /package/dist/web/assets/{racket-DI8v8nzD.js → racket-BA09P5Kg.js} +0 -0
  533. /package/dist/web/assets/{raku-CX1q9GW0.js → raku-DlpzU7Fe.js} +0 -0
  534. /package/dist/web/assets/{red-CSz3QEOw.js → red-l7VuCR6d.js} +0 -0
  535. /package/dist/web/assets/{reg-FMjhUQE-.js → reg-g_k7gQEr.js} +0 -0
  536. /package/dist/web/assets/{regexp-CCSe1Fc4.js → regexp-CT17B7I7.js} +0 -0
  537. /package/dist/web/assets/{rel-Ce0UO-OB.js → rel-DkPCS7Bp.js} +0 -0
  538. /package/dist/web/assets/{resolve-theme-B9Mgd5GG.js → resolve-theme-B0eotaPq.js} +0 -0
  539. /package/dist/web/assets/{riscv-BFZrdZtB.js → riscv-CYuFTw30.js} +0 -0
  540. /package/dist/web/assets/{ron-D0t4kvJG.js → ron-cY7u_yEu.js} +0 -0
  541. /package/dist/web/assets/{rose-pine-HzwmOzHM.js → rose-pine-Cr_h_Ubo.js} +0 -0
  542. /package/dist/web/assets/{rose-pine-dawn-CSp9xAF9.js → rose-pine-dawn-rRewaSZg.js} +0 -0
  543. /package/dist/web/assets/{rose-pine-moon-Cnzr2Cw0.js → rose-pine-moon-3VX5Xwca.js} +0 -0
  544. /package/dist/web/assets/{rosmsg-DEJ8Snbv.js → rosmsg-Du4ie5PU.js} +0 -0
  545. /package/dist/web/assets/{rust-2jBzrC0l.js → rust-B7xWL-Eh.js} +0 -0
  546. /package/dist/web/assets/{sass-DD75Izu_.js → sass-oXbOG8de.js} +0 -0
  547. /package/dist/web/assets/{scala-DpBKROIu.js → scala-nlZJhKHf.js} +0 -0
  548. /package/dist/web/assets/{scheme-DM2jzwUK.js → scheme-FZ9_Zy8D.js} +0 -0
  549. /package/dist/web/assets/{sdbl-C34Cg6e7.js → sdbl-D_lyvXiu.js} +0 -0
  550. /package/dist/web/assets/{shellscript-DxfzKSgU.js → shellscript-DRWRboAd.js} +0 -0
  551. /package/dist/web/assets/{slack-dark-DIIV3bpD.js → slack-dark-BGk2uVHu.js} +0 -0
  552. /package/dist/web/assets/{slack-ochin-BTkxWjEP.js → slack-ochin-PAoSX041.js} +0 -0
  553. /package/dist/web/assets/{smalltalk-Bm0qg6SA.js → smalltalk-qP0zvICo.js} +0 -0
  554. /package/dist/web/assets/{snazzy-light-ClAuuhn4.js → snazzy-light-B7uccpH6.js} +0 -0
  555. /package/dist/web/assets/{solarized-dark-93sEWmYT.js → solarized-dark-CbICLZs3.js} +0 -0
  556. /package/dist/web/assets/{solarized-light-C74FvgcO.js → solarized-light-CprWhyjj.js} +0 -0
  557. /package/dist/web/assets/{solidity-H9fSjkQP.js → solidity-B7pcm2K6.js} +0 -0
  558. /package/dist/web/assets/{splunk-CDTN2iAG.js → splunk-Co2LL4J_.js} +0 -0
  559. /package/dist/web/assets/{sql-CoqObhgo.js → sql-cETIdGnT.js} +0 -0
  560. /package/dist/web/assets/{ssh-config-C3Wv6qRp.js → ssh-config-DETG6JCD.js} +0 -0
  561. /package/dist/web/assets/{stylus-D0uTFXCy.js → stylus-tmTre2-O.js} +0 -0
  562. /package/dist/web/assets/{swift-DtMMgvRI.js → swift-BeKQbULV.js} +0 -0
  563. /package/dist/web/assets/{synthwave-84-DAroyZBu.js → synthwave-84-eCL4-Xdn.js} +0 -0
  564. /package/dist/web/assets/{system-verilog-Bj7X_lq4.js → system-verilog-CviwWvEx.js} +0 -0
  565. /package/dist/web/assets/{systemd-CH8ApCUs.js → systemd-WuoFIbBS.js} +0 -0
  566. /package/dist/web/assets/{talonscript-70lVC3cw.js → talonscript-B9VBu7VI.js} +0 -0
  567. /package/dist/web/assets/{tasl-WQR8VslV.js → tasl-CN7r11ky.js} +0 -0
  568. /package/dist/web/assets/{tcl-caTR_frn.js → tcl-e1cdhe3h.js} +0 -0
  569. /package/dist/web/assets/{terraform-CVRZ4SZ4.js → terraform-BEP0mfa_.js} +0 -0
  570. /package/dist/web/assets/{tokyo-night-CDyT1jCI.js → tokyo-night-BfA_dA37.js} +0 -0
  571. /package/dist/web/assets/{toml-B7D2mIDU.js → toml-BrDIfNnt.js} +0 -0
  572. /package/dist/web/assets/{tsv-2kdn5dqL.js → tsv-CyfGyE4i.js} +0 -0
  573. /package/dist/web/assets/{tsx-DJfG3fzg.js → tsx-BrFA8Iwf.js} +0 -0
  574. /package/dist/web/assets/{turtle-DaQac_UT.js → turtle-9GBtR0mP.js} +0 -0
  575. /package/dist/web/assets/{typescript-BLfAIchl.js → typescript-BuTRZ65V.js} +0 -0
  576. /package/dist/web/assets/{typespec-ymBaOi_c.js → typespec-CRiNNRXF.js} +0 -0
  577. /package/dist/web/assets/{typst-DkvUYMT-.js → typst-CmpTnnkl.js} +0 -0
  578. /package/dist/web/assets/{utils-E0yyGxXt.js → utils-B9H0d3Fh.js} +0 -0
  579. /package/dist/web/assets/{v-D4997FGs.js → v-DnIi2aab.js} +0 -0
  580. /package/dist/web/assets/{vala-AFg9DmKE.js → vala-B7VxCNZP.js} +0 -0
  581. /package/dist/web/assets/{vb-DNUJ9fOP.js → vb-DGoQ3pBT.js} +0 -0
  582. /package/dist/web/assets/{vendor-xterm-QDr0jvpJ.js → vendor-xterm-ClRVIJ-k.js} +0 -0
  583. /package/dist/web/assets/{verilog-BrnAQ3tF.js → verilog-zGOC4qwV.js} +0 -0
  584. /package/dist/web/assets/{vesper-DCZnFmY0.js → vesper-DXR9-06q.js} +0 -0
  585. /package/dist/web/assets/{vhdl-DoK4PjhE.js → vhdl-CCO0oz0l.js} +0 -0
  586. /package/dist/web/assets/{viml-D6EKG66q.js → viml-Dxwr-QNN.js} +0 -0
  587. /package/dist/web/assets/{vitesse-black-C6KILWdF.js → vitesse-black-Bhah7RxE.js} +0 -0
  588. /package/dist/web/assets/{vitesse-dark-BuSr6OT5.js → vitesse-dark-CGK6XVwc.js} +0 -0
  589. /package/dist/web/assets/{vitesse-light-M-eYyOoe.js → vitesse-light-ne5kfw8h.js} +0 -0
  590. /package/dist/web/assets/{vyper-CwSN64Jn.js → vyper-ErDFqVoP.js} +0 -0
  591. /package/dist/web/assets/{wasm-CVlf9Jwb.js → wasm-Bd258nS1.js} +0 -0
  592. /package/dist/web/assets/{wasm-BhQEkzil.js → wasm-DtWvUWGr.js} +0 -0
  593. /package/dist/web/assets/{wenyan-BC7irgM3.js → wenyan-EZe1IEYT.js} +0 -0
  594. /package/dist/web/assets/{wgsl-W-3UHMDO.js → wgsl-B1o5_I_9.js} +0 -0
  595. /package/dist/web/assets/{wikitext-T1DoFcm8.js → wikitext-C_rwp8An.js} +0 -0
  596. /package/dist/web/assets/{wit-DIrx_eCI.js → wit-gbYtF3rY.js} +0 -0
  597. /package/dist/web/assets/{wolfram-Cza4b443.js → wolfram-DrcQFe2n.js} +0 -0
  598. /package/dist/web/assets/{yaml-DOZ10aZe.js → yaml-CzDAObLX.js} +0 -0
  599. /package/dist/web/assets/{zenscript-DDAXkseY.js → zenscript-B-J1phtg.js} +0 -0
  600. /package/dist/web/assets/{zig-CrzwMpQE.js → zig-BlzNia0O.js} +0 -0
@@ -0,0 +1,103 @@
1
+ /**
2
+ * The two interruptions a mutation can raise: a name collision during paste, and the
3
+ * confirmation for a delete that skips the trash.
4
+ *
5
+ * Both are rendered by the window body from the state `useExplorerActions` owns, so the
6
+ * action modules stay free of React.
7
+ */
8
+
9
+ import { Button } from "@/components/ui/button";
10
+ import type { FsEntry } from "@/lib/fs-api";
11
+ import type { ExplorerDialogState } from "./actions/use-explorer-actions";
12
+ import { ExplorerModalShell } from "./explorer-modal-shell";
13
+ import { PropertiesDialog } from "./properties-dialog";
14
+
15
+ export interface ExplorerDialogsProps {
16
+ dialogs: ExplorerDialogState;
17
+ platform: string | undefined;
18
+ sep: string;
19
+ }
20
+
21
+ export function ExplorerDialogs({ dialogs, platform, sep }: ExplorerDialogsProps) {
22
+ const { collision, pendingDelete, permanentOverwrite, properties } = dialogs;
23
+
24
+ return (
25
+ <>
26
+ {collision && (
27
+ <ExplorerModalShell
28
+ open
29
+ // Dismissing without choosing must not silently overwrite anything.
30
+ onClose={() => collision.resolve("skip")}
31
+ title="An item with that name already exists"
32
+ description={collision.name}
33
+ footer={
34
+ <>
35
+ <Button variant="outline" onClick={() => collision.resolve("skip")}>Skip</Button>
36
+ <Button variant="outline" onClick={() => collision.resolve("keep-both")}>Keep both</Button>
37
+ <Button variant="destructive" onClick={() => collision.resolve("replace")}>Replace</Button>
38
+ </>
39
+ }
40
+ >
41
+ <p className="py-1 text-sm text-text-2">
42
+ Replacing moves the existing item to the Trash first, so it stays recoverable.
43
+ Keep both adds a numbered suffix.
44
+ </p>
45
+ </ExplorerModalShell>
46
+ )}
47
+
48
+ {pendingDelete && (
49
+ <ExplorerModalShell
50
+ open
51
+ onClose={dialogs.closeDelete}
52
+ title={`Delete ${pendingDelete.paths.length} item${pendingDelete.paths.length === 1 ? "" : "s"} permanently?`}
53
+ description="This cannot be undone — the items do not go to the Trash."
54
+ footer={
55
+ <>
56
+ <Button variant="outline" onClick={dialogs.closeDelete}>Cancel</Button>
57
+ <Button variant="destructive" onClick={dialogs.runPermanentDelete}>Delete permanently</Button>
58
+ </>
59
+ }
60
+ >
61
+ <ul className="space-y-0.5 py-1 text-sm text-text-2">
62
+ {pendingDelete.names.slice(0, 10).map((name) => (
63
+ <li key={name} className="truncate">{name}</li>
64
+ ))}
65
+ {pendingDelete.names.length > 10 && (
66
+ <li className="text-text-subtle">and {pendingDelete.names.length - 10} more…</li>
67
+ )}
68
+ </ul>
69
+ </ExplorerModalShell>
70
+ )}
71
+
72
+ {permanentOverwrite && (
73
+ <ExplorerModalShell
74
+ open
75
+ // Dismissing without choosing must not silently delete anything.
76
+ onClose={() => permanentOverwrite.resolve(false)}
77
+ title="This host has no Trash"
78
+ description={permanentOverwrite.name}
79
+ footer={
80
+ <>
81
+ <Button variant="outline" onClick={() => permanentOverwrite.resolve(false)}>Cancel</Button>
82
+ <Button variant="destructive" onClick={() => permanentOverwrite.resolve(true)}>Delete permanently</Button>
83
+ </>
84
+ }
85
+ >
86
+ <p className="py-1 text-sm text-text-2">
87
+ Replacing this item cannot go through the Trash on this host. Deleting it
88
+ permanently cannot be undone.
89
+ </p>
90
+ </ExplorerModalShell>
91
+ )}
92
+
93
+ {properties && (
94
+ <PropertiesDialog
95
+ entry={properties as FsEntry}
96
+ platform={platform}
97
+ sep={sep}
98
+ onClose={dialogs.closeProperties}
99
+ />
100
+ )}
101
+ </>
102
+ );
103
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * One modal presentation for every explorer prompt: a centred dialog on desktop, a
3
+ * bottom sheet below `md`.
4
+ *
5
+ * Properties, the collision prompt and the permanent-delete confirmation all need the
6
+ * same treatment, and the mobile rules say a dialog must become a sheet — doing that once
7
+ * here keeps the three call sites free of breakpoint logic.
8
+ */
9
+
10
+ import type { ReactNode } from "react";
11
+ import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/ui/dialog";
12
+ import { BottomSheet } from "@/components/ui/mobile-bottom-sheet";
13
+ import { useIsMobile } from "@/hooks/use-is-mobile";
14
+ import { cn } from "@/lib/utils";
15
+
16
+ export interface ExplorerModalShellProps {
17
+ open: boolean;
18
+ onClose(): void;
19
+ title: string;
20
+ description?: string;
21
+ children: ReactNode;
22
+ /** Rendered bottom-right on desktop, stacked full-width in the sheet's thumb zone. */
23
+ footer?: ReactNode;
24
+ className?: string;
25
+ }
26
+
27
+ export function ExplorerModalShell({
28
+ open, onClose, title, description, children, footer, className,
29
+ }: ExplorerModalShellProps) {
30
+ const isMobile = useIsMobile();
31
+
32
+ if (isMobile) {
33
+ return (
34
+ <BottomSheet open={open} onClose={onClose} className="p-4">
35
+ <div className={cn("space-y-3", className)}>
36
+ <div>
37
+ <h2 className="text-base font-semibold text-text">{title}</h2>
38
+ {description && <p className="mt-1 text-sm text-text-2">{description}</p>}
39
+ </div>
40
+ <div className="max-h-[50vh] overflow-y-auto">{children}</div>
41
+ {/* Primary actions sit at the bottom of the sheet, inside the thumb zone. */}
42
+ {footer && <div className="flex flex-col gap-2 pt-1">{footer}</div>}
43
+ </div>
44
+ </BottomSheet>
45
+ );
46
+ }
47
+
48
+ return (
49
+ <Dialog open={open} onOpenChange={(next) => { if (!next) onClose(); }}>
50
+ <DialogContent className={cn("sm:max-w-md", className)}>
51
+ <DialogHeader>
52
+ <DialogTitle>{title}</DialogTitle>
53
+ {description && <DialogDescription>{description}</DialogDescription>}
54
+ </DialogHeader>
55
+ <div className="max-h-[60vh] overflow-y-auto">{children}</div>
56
+ {footer && <div className="flex justify-end gap-2 pt-2">{footer}</div>}
57
+ </DialogContent>
58
+ </Dialog>
59
+ );
60
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * PPM's own sidebar pins — folders the user pinned inside PPM, kept apart from the
3
+ * OS-provided pins (Quick Access / Finder Favorites / GTK-KDE bookmarks) which are
4
+ * read-only and re-read from the host on every load.
5
+ */
6
+
7
+ import { create } from "zustand";
8
+
9
+ export interface ExplorerPin {
10
+ name: string;
11
+ path: string;
12
+ }
13
+
14
+ const PINS_KEY = "ppm-explorer-pins";
15
+ const MAX_PINS = 50;
16
+
17
+ function loadPins(): ExplorerPin[] {
18
+ try {
19
+ const raw = localStorage.getItem(PINS_KEY);
20
+ const parsed: unknown = raw ? JSON.parse(raw) : [];
21
+ if (!Array.isArray(parsed)) return [];
22
+ return parsed
23
+ .filter((p): p is ExplorerPin =>
24
+ !!p && typeof (p as ExplorerPin).path === "string" && typeof (p as ExplorerPin).name === "string")
25
+ .slice(0, MAX_PINS);
26
+ } catch {
27
+ return [];
28
+ }
29
+ }
30
+
31
+ function savePins(pins: ExplorerPin[]): void {
32
+ try {
33
+ localStorage.setItem(PINS_KEY, JSON.stringify(pins));
34
+ } catch {
35
+ /* quota or private mode — pins simply do not persist */
36
+ }
37
+ }
38
+
39
+ interface PinsStore {
40
+ pins: ExplorerPin[];
41
+ isPinned(path: string): boolean;
42
+ pin(pin: ExplorerPin): void;
43
+ unpin(path: string): void;
44
+ }
45
+
46
+ export const useExplorerPinsStore = create<PinsStore>((set, get) => ({
47
+ pins: loadPins(),
48
+
49
+ isPinned: (path) => get().pins.some((p) => p.path === path),
50
+
51
+ pin: (entry) => {
52
+ if (get().isPinned(entry.path)) return;
53
+ const pins = [...get().pins, entry].slice(0, MAX_PINS);
54
+ savePins(pins);
55
+ set({ pins });
56
+ },
57
+
58
+ unpin: (path) => {
59
+ const pins = get().pins.filter((p) => p.path !== path);
60
+ savePins(pins);
61
+ set({ pins });
62
+ },
63
+ }));
@@ -0,0 +1,198 @@
1
+ /**
2
+ * Places sidebar: PPM pins, the OS's own pinned folders, the known folders, and the
3
+ * drives.
4
+ *
5
+ * Host-info provider failures arrive as `warnings[]` rather than as an error — a Mac
6
+ * without Full Disk Access still has drives and known folders — so they render as a muted
7
+ * hint row instead of replacing the sidebar.
8
+ */
9
+
10
+ import type { ComponentType } from "react";
11
+ import { AlertTriangle, HardDrive, Pin, Usb, Network } from "lucide-react";
12
+ import type { HostInfo, Drive } from "../../../types/system";
13
+ import { cn } from "@/lib/utils";
14
+ import { DROP_TARGET_CLASS } from "./dnd/drop-target-style";
15
+ import type { DropRunner } from "./dnd/entry-drop-executor";
16
+ import { usePathDropTarget } from "./dnd/use-path-drop-target";
17
+ import { useDropTransfer } from "./dnd/use-drop-transfer";
18
+ import { useExplorerPinsStore } from "./explorer-pins-store";
19
+ import { FileTypeIcon } from "./icons/file-type-icon";
20
+ import type { SkinVocab } from "./skins/skin-types";
21
+ import { usePrefersCoarsePointer } from "./use-coarse-long-press";
22
+
23
+ /** A folder-type place row draws the current skin's folder glyph via `FileTypeIcon`'s context. */
24
+ function FolderPlaceIcon({ className }: { className?: string }) {
25
+ return <FileTypeIcon name="" kind="directory" className={cn("size-4 shrink-0", className)} />;
26
+ }
27
+
28
+ const DRIVE_ICON: Record<Drive["kind"], typeof HardDrive> = {
29
+ fixed: HardDrive,
30
+ removable: Usb,
31
+ network: Network,
32
+ unknown: HardDrive,
33
+ };
34
+
35
+ type PlaceIcon = ComponentType<{ className?: string }>;
36
+
37
+ interface PlaceProps {
38
+ label: string;
39
+ path: string;
40
+ active: boolean;
41
+ icon: PlaceIcon;
42
+ onNavigate(path: string): void;
43
+ onUnpin?(): void;
44
+ /** Every place is a directory, so a drop always has somewhere valid to land. */
45
+ run: DropRunner;
46
+ }
47
+
48
+ function Place({ label, path, active, icon: Icon, onNavigate, onUnpin, run }: PlaceProps) {
49
+ // Gated on real pointer coarseness, not a `md:` breakpoint — an iPad is ≥768px but has no
50
+ // mouse, so a breakpoint-only rule was silently dropping the 44px minimum for it.
51
+ const coarse = usePrefersCoarsePointer();
52
+ const drop = usePathDropTarget({ targetDir: path, run });
53
+ return (
54
+ <div className="group/place relative flex items-center">
55
+ <button
56
+ type="button"
57
+ title={path}
58
+ onClick={() => onNavigate(path)}
59
+ className={cn(
60
+ "flex w-full items-center gap-2 rounded px-2 py-1 text-left text-[13px]",
61
+ coarse ? "min-h-[44px]" : "min-h-0",
62
+ "can-hover:hover:bg-surface-elevated",
63
+ active ? "bg-accent-wash text-text" : "text-text-2",
64
+ drop.isOver && DROP_TARGET_CLASS,
65
+ )}
66
+ {...drop.handlers}
67
+ >
68
+ <Icon className="size-4 shrink-0 text-text-subtle" />
69
+ <span className="truncate">{label}</span>
70
+ </button>
71
+ {onUnpin && (
72
+ <button
73
+ type="button"
74
+ aria-label={`Unpin ${label}`}
75
+ title="Unpin"
76
+ onClick={onUnpin}
77
+ // Always reachable on touch; only revealed on hover where hovering exists.
78
+ className="absolute right-1 rounded p-1 text-text-subtle can-hover:opacity-0 can-hover:group-hover/place:opacity-100 can-hover:hover:text-text"
79
+ >
80
+ <Pin className="size-3.5" />
81
+ </button>
82
+ )}
83
+ </div>
84
+ );
85
+ }
86
+
87
+ function Section({ title, children }: { title: string; children: React.ReactNode }) {
88
+ return (
89
+ <div className="pb-2">
90
+ <p className="px-2 pb-0.5 pt-2 text-[10px] font-semibold uppercase tracking-wide text-text-subtle">
91
+ {title}
92
+ </p>
93
+ {children}
94
+ </div>
95
+ );
96
+ }
97
+
98
+ /** Used when a caller renders the sidebar without a resolved skin (defensive default). */
99
+ const DEFAULT_VOCAB: SkinVocab = { home: "Home", pinned: "Quick access", known: "Folders", drives: "Drives" };
100
+
101
+ export interface ExplorerSidebarProps {
102
+ host: HostInfo | null;
103
+ currentPath: string;
104
+ onNavigate(path: string): void;
105
+ /** Section labels for the current OS skin — Finder says "Favorites"/"Locations". */
106
+ vocab?: SkinVocab;
107
+ }
108
+
109
+ export function ExplorerSidebar({ host, currentPath, onNavigate, vocab = DEFAULT_VOCAB }: ExplorerSidebarProps) {
110
+ const pins = useExplorerPinsStore((s) => s.pins);
111
+ const unpin = useExplorerPinsStore((s) => s.unpin);
112
+ const isActive = (path: string) => path === currentPath;
113
+ // One drop-transfer context for the whole sidebar — every place lands through the same
114
+ // collision prompt rather than each row owning its own dialog state.
115
+ const { run, prompts } = useDropTransfer(host?.sep ?? "/", host?.platform);
116
+
117
+ return (
118
+ <aside
119
+ aria-label="Places"
120
+ data-testid="explorer-sidebar"
121
+ className="hidden w-44 shrink-0 overflow-y-auto border-r border-border bg-[var(--x-sidebar-bg,var(--panel-2))] px-1 py-1 sm:block"
122
+ >
123
+ {pins.length > 0 && (
124
+ <Section title="Pinned">
125
+ {pins.map((pin) => (
126
+ <Place
127
+ key={pin.path}
128
+ label={pin.name}
129
+ path={pin.path}
130
+ icon={Pin}
131
+ active={isActive(pin.path)}
132
+ onNavigate={onNavigate}
133
+ onUnpin={() => unpin(pin.path)}
134
+ run={run}
135
+ />
136
+ ))}
137
+ </Section>
138
+ )}
139
+
140
+ {host && host.pinned.length > 0 && (
141
+ <Section title={vocab.pinned}>
142
+ {host.pinned.map((entry) => (
143
+ <Place
144
+ key={entry.path}
145
+ label={entry.name}
146
+ path={entry.path}
147
+ icon={FolderPlaceIcon}
148
+ active={isActive(entry.path)}
149
+ onNavigate={onNavigate}
150
+ run={run}
151
+ />
152
+ ))}
153
+ </Section>
154
+ )}
155
+
156
+ {host && (
157
+ <Section title={vocab.known}>
158
+ <Place label={vocab.home} path={host.homedir} icon={FolderPlaceIcon} active={isActive(host.homedir)} onNavigate={onNavigate} run={run} />
159
+ {host.knownFolders.map((folder) => (
160
+ <Place
161
+ key={folder.path}
162
+ label={folder.name}
163
+ path={folder.path}
164
+ icon={FolderPlaceIcon}
165
+ active={isActive(folder.path)}
166
+ onNavigate={onNavigate}
167
+ run={run}
168
+ />
169
+ ))}
170
+ </Section>
171
+ )}
172
+
173
+ {host && host.drives.length > 0 && (
174
+ <Section title={vocab.drives}>
175
+ {host.drives.map((drive) => (
176
+ <Place
177
+ key={drive.path}
178
+ label={drive.label ? `${drive.label} (${drive.name})` : drive.name}
179
+ path={drive.path}
180
+ icon={DRIVE_ICON[drive.kind]}
181
+ active={isActive(drive.path)}
182
+ onNavigate={onNavigate}
183
+ run={run}
184
+ />
185
+ ))}
186
+ </Section>
187
+ )}
188
+
189
+ {host?.warnings.map((warning) => (
190
+ <p key={warning} className="flex gap-1.5 px-2 py-1 text-[11px] leading-snug text-text-subtle">
191
+ <AlertTriangle className="mt-0.5 size-3 shrink-0" />
192
+ <span>{warning}</span>
193
+ </p>
194
+ ))}
195
+ {prompts}
196
+ </aside>
197
+ );
198
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Toolbar "Sort" menu: the only sort control reachable from Icons and Column view, which
3
+ * have no clickable column header of their own (List view keeps that shortcut too — see
4
+ * `views/list-view.tsx`). Backed by the same `prefs.sort` every view already reads.
5
+ */
6
+
7
+ import { ArrowUpDown } from "lucide-react";
8
+ import {
9
+ DropdownMenu,
10
+ DropdownMenuContent,
11
+ DropdownMenuLabel,
12
+ DropdownMenuRadioGroup,
13
+ DropdownMenuRadioItem,
14
+ DropdownMenuSeparator,
15
+ DropdownMenuTrigger,
16
+ } from "@/components/ui/dropdown-menu";
17
+ import { useExplorerStore, type SortDir, type SortKey } from "./explorer-store";
18
+ import { SORT_DIR_OPTIONS, SORT_KEY_OPTIONS, sortDirLabel, sortKeyLabel } from "./sort-options";
19
+ import { toolbarButtonClass } from "./toolbar-icon-button";
20
+
21
+ export interface ExplorerSortMenuProps {
22
+ coarse: boolean;
23
+ }
24
+
25
+ export function ExplorerSortMenu({ coarse }: ExplorerSortMenuProps) {
26
+ const sort = useExplorerStore((s) => s.sort);
27
+ const setPrefs = useExplorerStore((s) => s.setPrefs);
28
+
29
+ // No skin currently defines a `vocab` slot for this label, so both the Windows and
30
+ // macOS chrome fall back to the same plain word.
31
+ const label = "Sort";
32
+ const title = `${label}: ${sortKeyLabel(sort.key)}, ${sortDirLabel(sort.dir)}`;
33
+
34
+ return (
35
+ <DropdownMenu>
36
+ <DropdownMenuTrigger asChild>
37
+ <button type="button" aria-label={label} title={title} className={toolbarButtonClass(coarse)}>
38
+ <ArrowUpDown className="size-4" />
39
+ </button>
40
+ </DropdownMenuTrigger>
41
+ <DropdownMenuContent align="end">
42
+ <DropdownMenuLabel>Sort by</DropdownMenuLabel>
43
+ <DropdownMenuRadioGroup
44
+ value={sort.key}
45
+ onValueChange={(key) => setPrefs({ sort: { key: key as SortKey, dir: sort.dir } })}
46
+ >
47
+ {SORT_KEY_OPTIONS.map(({ key, label: keyLabel }) => (
48
+ <DropdownMenuRadioItem key={key} value={key}>
49
+ {keyLabel}
50
+ </DropdownMenuRadioItem>
51
+ ))}
52
+ </DropdownMenuRadioGroup>
53
+ <DropdownMenuSeparator />
54
+ <DropdownMenuLabel>Order</DropdownMenuLabel>
55
+ <DropdownMenuRadioGroup
56
+ value={sort.dir}
57
+ onValueChange={(dir) => setPrefs({ sort: { key: sort.key, dir: dir as SortDir } })}
58
+ >
59
+ {SORT_DIR_OPTIONS.map(({ dir, label: dirLabel }) => (
60
+ <DropdownMenuRadioItem key={dir} value={dir}>
61
+ {dirLabel}
62
+ </DropdownMenuRadioItem>
63
+ ))}
64
+ </DropdownMenuRadioGroup>
65
+ </DropdownMenuContent>
66
+ </DropdownMenu>
67
+ );
68
+ }
@@ -0,0 +1,35 @@
1
+ /** Item count, selection count and the selected size — the strip along the window's foot. */
2
+
3
+ import type { FsEntry } from "@/lib/fs-api";
4
+ import { formatSize } from "./format-file-meta";
5
+ import { totalSize } from "./sort-and-filter-entries";
6
+
7
+ export interface ExplorerStatusBarProps {
8
+ /** Rows currently visible (after filtering). */
9
+ entries: FsEntry[];
10
+ selection: Set<string>;
11
+ /** True when the server capped the listing, so the counts are a lower bound. */
12
+ truncated: boolean;
13
+ }
14
+
15
+ export function ExplorerStatusBar({ entries, selection, truncated }: ExplorerStatusBarProps) {
16
+ const selected = entries.filter((e) => selection.has(e.path));
17
+ const parts = [`${entries.length}${truncated ? "+" : ""} item${entries.length === 1 ? "" : "s"}`];
18
+ if (selected.length > 0) {
19
+ parts.push(`${selected.length} selected`);
20
+ const bytes = totalSize(selected);
21
+ if (bytes > 0) parts.push(formatSize(bytes));
22
+ }
23
+
24
+ return (
25
+ <div
26
+ data-testid="explorer-status"
27
+ className="flex shrink-0 items-center gap-2 border-t border-border bg-panel-2 px-2 py-1 text-[11px] text-text-subtle"
28
+ >
29
+ {parts.join(" · ")}
30
+ {truncated && (
31
+ <span className="ml-auto">Listing capped — narrow the filter to see the rest.</span>
32
+ )}
33
+ </div>
34
+ );
35
+ }