@hienlh/ppm 0.18.10 → 0.18.12

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 (543) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +81 -23
  3. package/assets/skills/ppm/SKILL.md +1 -1
  4. package/assets/skills/ppm/references/http-api.md +1 -1
  5. package/dist/web/assets/adaptive-context-menu-DGCKKeTy.js +1 -0
  6. package/dist/web/assets/ai-resource-editor-BOHHTTe7.js +1 -0
  7. package/dist/web/assets/ai-settings-section-BigC_nZR.js +1 -0
  8. package/dist/web/assets/{angular-html-Ctz0zN01.js → angular-html-BYPaydvh.js} +1 -1
  9. package/dist/web/assets/{angular-ts-QXHpgB1C.js → angular-ts-Bb4AMKlk.js} +1 -1
  10. package/dist/web/assets/api-client-DTZEgjBQ.js +1 -0
  11. package/dist/web/assets/{api-settings-kQHV6pYZ.js → api-settings-Bd3M4YpI.js} +1 -1
  12. package/dist/web/assets/api-settings-kd1j4iR8.js +1 -0
  13. package/dist/web/assets/{api-themes-CrK0tkW_.js → api-themes-Cpx419SL.js} +1 -1
  14. package/dist/web/assets/{apl-b9KVk-O4.js → apl-DB2VjFCS.js} +1 -1
  15. package/dist/web/assets/architecture-PBZL5I3N-8dCMT9r7.js +1 -0
  16. package/dist/web/assets/{astro-BlFEeGYr.js → astro-BeoJdVpk.js} +1 -1
  17. package/dist/web/assets/{audio-preview-CZLmhf__.js → audio-preview-BgFuTn-0.js} +1 -1
  18. package/dist/web/assets/{blade-CGkj2MUI.js → blade-Cf2q1sPf.js} +1 -1
  19. package/dist/web/assets/{bsl-CVsbb6ap.js → bsl-W1kOaNpu.js} +1 -1
  20. package/dist/web/assets/{button-BA_fJOtX.js → button-5zTrkEoN.js} +1 -1
  21. package/dist/web/assets/{cairo-BbIHl2iE.js → cairo-BoAZFcje.js} +1 -1
  22. package/dist/web/assets/chat-tab-E3bf_V8X.js +15 -0
  23. package/dist/web/assets/chevron-down-Dp0rpHb8.js +1 -0
  24. package/dist/web/assets/clipboard-7fw0Shic.js +1 -0
  25. package/dist/web/assets/{cobol-BWSGjmWb.js → cobol-B0Nm7RXj.js} +1 -1
  26. package/dist/web/assets/code-editor-BUlM2gXk.js +10 -0
  27. package/dist/web/assets/{coffee-CWGNOxds.js → coffee-BakMn3on.js} +1 -1
  28. package/dist/web/assets/{conflict-editor-fRTU3f1o.js → conflict-editor-BUs5k9q_.js} +4 -4
  29. package/dist/web/assets/context-menu-Bq92km4s.js +1 -0
  30. package/dist/web/assets/{cpp-DHGV24J2.js → cpp-BRAJQHK2.js} +1 -1
  31. package/dist/web/assets/{crystal-Vlwf2UMP.js → crystal-kqqO3zkK.js} +1 -1
  32. package/dist/web/assets/{csv-preview-D1d0cxOJ.js → csv-preview-ByoDgLAZ.js} +1 -1
  33. package/dist/web/assets/{data-grid-overlay-editor-D9il5DZS.js → data-grid-overlay-editor-Brkf9z41.js} +1 -1
  34. package/dist/web/assets/database-viewer-Btc3h8Yu.js +1 -0
  35. package/dist/web/assets/dialog-DwtGlowE.js +1 -0
  36. package/dist/web/assets/diff-viewer-CZaDnR4w.js +4 -0
  37. package/dist/web/assets/docx-preview-DAD_vg59.js +12 -0
  38. package/dist/web/assets/{edge-Bhqk64zS.js → edge-Cq1ZKZuE.js} +1 -1
  39. package/dist/web/assets/{edit-diff-preview-gq6ALf2B.js → edit-diff-preview-B_VE7ppQ.js} +1 -1
  40. package/dist/web/assets/{elixir-D466WCFm.js → elixir-BM_JoJRk.js} +1 -1
  41. package/dist/web/assets/{elm-Bfs2qNPR.js → elm-Dw7oO08Y.js} +1 -1
  42. package/dist/web/assets/{erb-WI7jUaB6.js → erb-CfKOGAfk.js} +1 -1
  43. package/dist/web/assets/{erlang-BCBe8nCc.js → erlang-DlDmGVeE.js} +1 -1
  44. package/dist/web/assets/{esm-CZs9WVDO.js → esm-DGAP0GFh.js} +1 -1
  45. package/dist/web/assets/explorer-body-9aBmyVpZ.js +2 -0
  46. package/dist/web/assets/explorer-window-content-DRtqoSPA.js +1 -0
  47. package/dist/web/assets/extension-store-Cpfh2vMm.js +1 -0
  48. package/dist/web/assets/{extension-webview-BH_mWYMe.js → extension-webview-B2OnjuCu.js} +2 -2
  49. package/dist/web/assets/external-link-B8BynhvY.js +1 -0
  50. package/dist/web/assets/file-store-aOERIEo-.js +1 -0
  51. package/dist/web/assets/folder-symlink-B8XrtvQK.js +1 -0
  52. package/dist/web/assets/{fortran-fixed-form-CXLIv8Ox.js → fortran-fixed-form-XnAhQWxS.js} +1 -1
  53. package/dist/web/assets/{fsharp-CZsYmiw9.js → fsharp-CdNvy0PG.js} +1 -1
  54. package/dist/web/assets/{gdresource-BGRvoWfC.js → gdresource-DxuG5i8i.js} +1 -1
  55. package/dist/web/assets/{git-commit-DH6mY3Km.js → git-commit-3lMonsur.js} +1 -1
  56. package/dist/web/assets/git-log-panel-Co0PBPHC.js +1 -0
  57. package/dist/web/assets/{git-rebase-C5Gql6Ma.js → git-rebase-N8Z9kIMf.js} +1 -1
  58. package/dist/web/assets/gitGraph-HDMCJU4V-2e_8dfbs.js +1 -0
  59. package/dist/web/assets/{glide-data-grid-n4ox_uev.js → glide-data-grid-C4_zIneN.js} +8 -8
  60. package/dist/web/assets/{glimmer-js-1-6JMJlj.js → glimmer-js-Dp9OXiib.js} +1 -1
  61. package/dist/web/assets/{glimmer-ts-C_Njj0nK.js → glimmer-ts-CDVKBcDj.js} +1 -1
  62. package/dist/web/assets/{glsl-DbkxE1TN.js → glsl-DPJxI4us.js} +1 -1
  63. package/dist/web/assets/{graphql-BK75fiXl.js → graphql-BrFhaQQl.js} +1 -1
  64. package/dist/web/assets/group-chat-tab-rOd8J8GC.js +1 -0
  65. package/dist/web/assets/{hack-DG151vit.js → hack-BzXbDMlA.js} +1 -1
  66. package/dist/web/assets/{haml-DKeIPQWM.js → haml-CPpkX0s5.js} +1 -1
  67. package/dist/web/assets/{handlebars-398uCI13.js → handlebars-BqrApy52.js} +1 -1
  68. package/dist/web/assets/{html-NLWdst5q.js → html-DmjUl-OA.js} +1 -1
  69. package/dist/web/assets/{html-derivative-CJf_Le2z.js → html-derivative-Cnd6XFR5.js} +1 -1
  70. package/dist/web/assets/{http-G1K2FozA.js → http-DMLWYun2.js} +1 -1
  71. package/dist/web/assets/{hurl-WDC6sSBz.js → hurl-CKkCVxbj.js} +1 -1
  72. package/dist/web/assets/{hxml-Dc3jBXuf.js → hxml-CAx19TtQ.js} +1 -1
  73. package/dist/web/assets/image-preview-DHUoylQ1.js +1 -0
  74. package/dist/web/assets/index-BImUaigO.js +52 -0
  75. package/dist/web/assets/index-CSfi6DSU.css +2 -0
  76. package/dist/web/assets/info-3K5VOQVL-BZi1Gha1.js +1 -0
  77. package/dist/web/assets/input-DcEk7mA3.js +1 -0
  78. package/dist/web/assets/{jinja-CWsQj2y0.js → jinja-BmB9YN9l.js} +1 -1
  79. package/dist/web/assets/{jison-CciJg2NW.js → jison-BaVsKKpw.js} +1 -1
  80. package/dist/web/assets/{julia-IOQNJAB7.js → julia-BgVBLveX.js} +1 -1
  81. package/dist/web/assets/{just-BGdHchwS.js → just-C2ENIbl9.js} +1 -1
  82. package/dist/web/assets/keybindings-store-BGIyqXHI.js +1 -0
  83. package/dist/web/assets/keybindings-store-CzV2sPls.js +1 -0
  84. package/dist/web/assets/{latex-D6TOl-L2.js → latex-BiDIWxKL.js} +1 -1
  85. package/dist/web/assets/{liquid-CVSvu_Wn.js → liquid-NxpapreE.js} +1 -1
  86. package/dist/web/assets/loader-circle-gSPVxfvH.js +1 -0
  87. package/dist/web/assets/lock-Did-87UV.js +1 -0
  88. package/dist/web/assets/{lua-CcKiU6HW.js → lua-DVepQvwH.js} +1 -1
  89. package/dist/web/assets/markdown-renderer-CcbR33VG.js +1 -0
  90. package/dist/web/assets/{markdown-renderer-B317vEys.js → markdown-renderer-DlcDhgrF.js} +3 -3
  91. package/dist/web/assets/{marko--UOicMGo.js → marko-CJ2606Xl.js} +1 -1
  92. package/dist/web/assets/{mdc-D690aU2C.js → mdc-D2bjqclE.js} +1 -1
  93. package/dist/web/assets/{media-url-CylYQld1.js → media-url-H17XJF-I.js} +1 -1
  94. package/dist/web/assets/mobile-bottom-sheet-g-r2hCFa.js +1 -0
  95. package/dist/web/assets/mobile-explorer-sheet-SIwQXlwA.js +1 -0
  96. package/dist/web/assets/monitor-Dv8vn_6O.js +1 -0
  97. package/dist/web/assets/{nextflow-DR8PhpF8.js → nextflow-BtJwUbfF.js} +1 -1
  98. package/dist/web/assets/{nginx-Qb9pUk1g.js → nginx-j4gyIhHE.js} +1 -1
  99. package/dist/web/assets/{nim-DLa8R3NS.js → nim-ClH_gjP5.js} +1 -1
  100. package/dist/web/assets/notification-store-DV5QtUTg.js +1 -0
  101. package/dist/web/assets/{number-overlay-editor-D9SkFg1Y.js → number-overlay-editor-C1EqJnWq.js} +1 -1
  102. package/dist/web/assets/{overview-panel-BxDohIEa.js → overview-panel-vTeeJYVZ.js} +1 -1
  103. package/dist/web/assets/packet-RMMSAZCW-o5htEcin.js +1 -0
  104. package/dist/web/assets/panel-store-BSnkjgHt.js +1 -0
  105. package/dist/web/assets/pdf-preview-CqFGRY0Z.js +1 -0
  106. package/dist/web/assets/pencil-BlIIg6RH.js +1 -0
  107. package/dist/web/assets/{perl-AMNGIneF.js → perl-C9H7X7CT.js} +1 -1
  108. package/dist/web/assets/{php-CDsOOxXn.js → php-Bx2U-cQ_.js} +1 -1
  109. package/dist/web/assets/pie-UPGHQEXC-BXAIFSAD.js +1 -0
  110. package/dist/web/assets/play-4MZi1Axp.js +1 -0
  111. package/dist/web/assets/portal-container-context-Cm5HipFr.js +1 -0
  112. package/dist/web/assets/{postgres-viewer-BWZLW7kI.js → postgres-viewer-DHwcQucn.js} +3 -3
  113. package/dist/web/assets/process-table-BGRJNlpn.js +1 -0
  114. package/dist/web/assets/{project-store-B8BkHXy5.js → project-store--nvQiy75.js} +1 -1
  115. package/dist/web/assets/{pug-C2kdkhQ6.js → pug-Cw74sKsE.js} +1 -1
  116. package/dist/web/assets/{qml-DRDkUp75.js → qml-BXD94Eqz.js} +1 -1
  117. package/dist/web/assets/radar-KQ55EAFF-Dbt2Aebl.js +1 -0
  118. package/dist/web/assets/{razor-wY_6wUeC.js → razor-DZ0-Ge0S.js} +1 -1
  119. package/dist/web/assets/refresh-cw-B06yaBrW.js +1 -0
  120. package/dist/web/assets/rotate-ccw-COXu_9oj.js +1 -0
  121. package/dist/web/assets/{rst-BRpofyNs.js → rst-Dtdh0QUj.js} +1 -1
  122. package/dist/web/assets/{ruby-ieATBhWm.js → ruby-BC51BW2Q.js} +1 -1
  123. package/dist/web/assets/{run-in-terminal-CyS5Itj-.js → run-in-terminal-Sd3KyjN4.js} +1 -1
  124. package/dist/web/assets/{sas-CoOOEbOO.js → sas-BN8i4qOU.js} +1 -1
  125. package/dist/web/assets/scroll-area-0gljZ6lF.js +1 -0
  126. package/dist/web/assets/{scss-_nWV0bsb.js → scss-H-QtA7Rz.js} +1 -1
  127. package/dist/web/assets/send-BlyNJAzy.js +1 -0
  128. package/dist/web/assets/{send-to-chat-BcO39BDR.js → send-to-chat-u6m8l-rH.js} +1 -1
  129. package/dist/web/assets/{settings-store-C20lqh0G.js → settings-store-CHY6Kzin.js} +2 -2
  130. package/dist/web/assets/settings-tab-Dic6TKkU.js +1 -0
  131. package/dist/web/assets/settings-tab-IY6K1MiZ.js +3 -0
  132. package/dist/web/assets/{shaderlab-XkqfIfO8.js → shaderlab-CalNsj_x.js} +1 -1
  133. package/dist/web/assets/shallow-DYo6goJ4.js +1 -0
  134. package/dist/web/assets/{shellsession-BKBIqTlM.js → shellsession-BFrcoR8x.js} +1 -1
  135. package/dist/web/assets/{soy-oVDnPzzh.js → soy-CNbku7vP.js} +1 -1
  136. package/dist/web/assets/{sparql-N2VclEsF.js → sparql-BN_orcVp.js} +1 -1
  137. package/dist/web/assets/{sql-query-editor-BwPjEaP9.js → sql-query-editor-C6pC3I8l.js} +1 -1
  138. package/dist/web/assets/sqlite-viewer-DTr5PzUb.js +1 -0
  139. package/dist/web/assets/{stata-BuuClVDg.js → stata-C6a5Ijzq.js} +1 -1
  140. package/dist/web/assets/{surrealql-DE5_63MS.js → surrealql-ClplI_HY.js} +1 -1
  141. package/dist/web/assets/{svelte--YWjlOrK.js → svelte-DNm-UNXB.js} +1 -1
  142. package/dist/web/assets/switch-DKvKya9y.js +1 -0
  143. package/dist/web/assets/system-monitor-body-iwGiCns9.js +2 -0
  144. package/dist/web/assets/system-monitor-tab-DdXQhEel.js +1 -0
  145. package/dist/web/assets/system-monitor-window-content-BUqRsPK2.js +1 -0
  146. package/dist/web/assets/tab-host-window-content-BnqGPu8a.js +1 -0
  147. package/dist/web/assets/{tab-store-DAsvpx4t.js → tab-store-CJuJRapl.js} +1 -1
  148. package/dist/web/assets/team-member-sheet-LkAFSCvb.js +2 -0
  149. package/dist/web/assets/team-member-window-content-T4Q5JI-G.js +1 -0
  150. package/dist/web/assets/{templ-MlpvJx4a.js → templ-CSdqVobu.js} +1 -1
  151. package/dist/web/assets/terminal-tab-Bb2rZegQ.js +3 -0
  152. package/dist/web/assets/{tex-0loAoXJG.js → tex-DzSJ4kcZ.js} +1 -1
  153. package/dist/web/assets/text-wrap-CBT4Gxtg.js +1 -0
  154. package/dist/web/assets/tool-cards-lhqhrDTT.js +8 -0
  155. package/dist/web/assets/trash-2-Bk4yYlck.js +1 -0
  156. package/dist/web/assets/treemap-KZPCXAKY-DUbnl9dz.js +1 -0
  157. package/dist/web/assets/triangle-alert-B8EYecpe.js +1 -0
  158. package/dist/web/assets/{ts-tags-pt-Ug0hK.js → ts-tags-C28w3bTg.js} +1 -1
  159. package/dist/web/assets/{twig-DOePpLOL.js → twig-i5jY3QXB.js} +1 -1
  160. package/dist/web/assets/upload-BNlX8D07.js +1 -0
  161. package/dist/web/assets/{use-blob-url-BKyVxOZw.js → use-blob-url-Dsq9OjTh.js} +1 -1
  162. package/dist/web/assets/{use-monaco-theme-DSCdlrjO.js → use-monaco-theme-BZvlsoBv.js} +1 -1
  163. package/dist/web/assets/use-open-team-member-DkiEjFYE.js +1 -0
  164. package/dist/web/assets/{use-websocket-iJfc7EbK.js → use-websocket-B8R50f7f.js} +1 -1
  165. package/dist/web/assets/{vendor-mermaid-DrwG0NYt.js → vendor-mermaid-By4AVvJY.js} +1 -1
  166. package/dist/web/assets/video-preview-m0-3p7QZ.js +1 -0
  167. package/dist/web/assets/{vue-D6f-rprj.js → vue-Ceyet_lv.js} +1 -1
  168. package/dist/web/assets/{vue-html-DEYRkS1V.js → vue-html-GuU7g_hg.js} +1 -1
  169. package/dist/web/assets/{vue-vine-CxSG2ojf.js → vue-vine-CxXoaJr2.js} +1 -1
  170. package/dist/web/assets/window-store-CsEW6jiE.js +1 -0
  171. package/dist/web/assets/{xml-DhrxbATj.js → xml-CbqOVhkP.js} +1 -1
  172. package/dist/web/assets/{xsl-CU0ZndUO.js → xsl-KfAmCauy.js} +1 -1
  173. package/dist/web/index.html +56 -27
  174. package/dist/web/sw.js +1 -1
  175. package/docs/code-standards.md +8 -0
  176. package/docs/codebase-summary.md +19 -5
  177. package/docs/design-guidelines.md +13 -2
  178. package/docs/project-roadmap.md +9 -0
  179. package/docs/system-architecture.md +83 -6
  180. package/package.json +1 -1
  181. package/src/web/components/chat/file-picker.tsx +5 -2
  182. package/src/web/components/chat/mode-selector.tsx +5 -2
  183. package/src/web/components/chat/model-selector.tsx +5 -2
  184. package/src/web/components/chat/model-thinking-selector.tsx +5 -2
  185. package/src/web/components/chat/provider-selector.tsx +5 -2
  186. package/src/web/components/chat/slash-command-picker.tsx +5 -2
  187. package/src/web/components/editor/code-editor.tsx +13 -3
  188. package/src/web/components/editor/conflict-editor.tsx +9 -0
  189. package/src/web/components/editor/diff-viewer.tsx +9 -0
  190. package/src/web/components/floating-window/floating-window.tsx +23 -15
  191. package/src/web/components/floating-window/pip/pip-caption-button.tsx +108 -0
  192. package/src/web/components/floating-window/pip/pip-focus-target.ts +58 -0
  193. package/src/web/components/floating-window/pip/pip-geometry.ts +46 -0
  194. package/src/web/components/floating-window/pip/pip-host.ts +156 -0
  195. package/src/web/components/floating-window/pip/pip-key-forward.ts +59 -0
  196. package/src/web/components/floating-window/pip/pip-resize-signal.ts +33 -0
  197. package/src/web/components/floating-window/pip/pip-style-copy.ts +108 -0
  198. package/src/web/components/floating-window/pip/pip-support.ts +33 -0
  199. package/src/web/components/floating-window/tab-host-window-content.tsx +80 -0
  200. package/src/web/components/floating-window/use-window-body-element.ts +67 -0
  201. package/src/web/components/floating-window/use-window-drag.ts +5 -0
  202. package/src/web/components/floating-window/use-window-gesture-context.ts +14 -0
  203. package/src/web/components/floating-window/use-window-resize.ts +5 -0
  204. package/src/web/components/floating-window/window-content-registry.ts +4 -16
  205. package/src/web/components/floating-window/window-layer.tsx +1 -2
  206. package/src/web/components/floating-window/window-persistence.ts +9 -2
  207. package/src/web/components/floating-window/window-pip-placeholder.tsx +31 -0
  208. package/src/web/components/floating-window/window-pip-registry.ts +69 -0
  209. package/src/web/components/floating-window/window-skin-chrome.tsx +21 -0
  210. package/src/web/components/floating-window/window-store-types.ts +8 -2
  211. package/src/web/components/layout/reparenting-tab.tsx +136 -0
  212. package/src/web/components/layout/tab-bar.tsx +2 -0
  213. package/src/web/components/layout/tab-pool-collect.ts +38 -2
  214. package/src/web/components/layout/tab-pool-registry.ts +48 -0
  215. package/src/web/components/layout/tab-pool.tsx +54 -168
  216. package/src/web/components/layout/tab-pop-out-menu-item.tsx +42 -0
  217. package/src/web/components/layout/use-window-panel-reconcile.ts +48 -0
  218. package/src/web/components/os-explorer/skins/macos-window-chrome.tsx +16 -7
  219. package/src/web/components/os-explorer/skins/windows-window-chrome.tsx +14 -8
  220. package/src/web/components/ui/context-menu.tsx +10 -3
  221. package/src/web/components/ui/dialog.tsx +10 -1
  222. package/src/web/components/ui/dropdown-menu.tsx +10 -3
  223. package/src/web/components/ui/mobile-bottom-sheet.tsx +7 -4
  224. package/src/web/components/ui/portal-container-context.tsx +40 -0
  225. package/src/web/components/ui/select.tsx +3 -1
  226. package/src/web/components/ui/tooltip.tsx +3 -1
  227. package/src/web/hooks/use-terminal.ts +24 -3
  228. package/src/web/stores/panel-store.ts +72 -7
  229. package/src/web/stores/panel-utils.ts +36 -0
  230. package/src/web/stores/window-panel-actions.ts +211 -0
  231. package/src/web/stores/window-panel-persistence.ts +115 -0
  232. package/src/web/stores/window-panel-reconcile.ts +97 -0
  233. package/.spike/group-protected-probe.ts +0 -21
  234. package/.spike/s.err +0 -63
  235. package/.spike/tunnel.err +0 -22
  236. package/.spike/w.err +0 -28
  237. package/dist/web/assets/ai-resource-editor-mdDKG-rw.js +0 -1
  238. package/dist/web/assets/api-client-CzABTreM.js +0 -1
  239. package/dist/web/assets/api-settings-nblja3Rk.js +0 -1
  240. package/dist/web/assets/architecture-PBZL5I3N-C7ra20CE.js +0 -1
  241. package/dist/web/assets/chat-tab-C060A94y.js +0 -15
  242. package/dist/web/assets/code-editor-WELegzdp.js +0 -10
  243. package/dist/web/assets/context-menu-Cq0u3SK9.js +0 -1
  244. package/dist/web/assets/database-viewer-DevnWTV4.js +0 -1
  245. package/dist/web/assets/diff-viewer-DGxVg1pD.js +0 -4
  246. package/dist/web/assets/docx-preview-Cx-zLwAw.js +0 -12
  247. package/dist/web/assets/explorer-body-j_4hVc34.js +0 -2
  248. package/dist/web/assets/explorer-window-content-DdrGwk3w.js +0 -1
  249. package/dist/web/assets/git-log-panel-CfpXRJcP.js +0 -1
  250. package/dist/web/assets/gitGraph-HDMCJU4V-D4hYLNJU.js +0 -1
  251. package/dist/web/assets/group-chat-tab-dYuuknLN.js +0 -1
  252. package/dist/web/assets/image-preview-Ss38ex8g.js +0 -1
  253. package/dist/web/assets/index-BiTiXgBZ.css +0 -2
  254. package/dist/web/assets/index-Ch8l9de-.js +0 -52
  255. package/dist/web/assets/info-3K5VOQVL-lRlrTlkb.js +0 -1
  256. package/dist/web/assets/keybindings-store-CDfTjwZX.js +0 -1
  257. package/dist/web/assets/markdown-renderer-CpRlpLHw.js +0 -1
  258. package/dist/web/assets/mobile-bottom-sheet-BUOJgiaZ.js +0 -1
  259. package/dist/web/assets/mobile-explorer-sheet-D1Bv9UCT.js +0 -1
  260. package/dist/web/assets/notification-store-KwTAZT8b.js +0 -1
  261. package/dist/web/assets/packet-RMMSAZCW-BIhk1mvp.js +0 -1
  262. package/dist/web/assets/panel-store-DCD82zc1.js +0 -1
  263. package/dist/web/assets/pdf-preview-dwRe54ht.js +0 -1
  264. package/dist/web/assets/pie-UPGHQEXC-SLS6i76l.js +0 -1
  265. package/dist/web/assets/process-table-CI-fnVsy.js +0 -1
  266. package/dist/web/assets/radar-KQ55EAFF-JJ6O1Er_.js +0 -1
  267. package/dist/web/assets/settings-tab-mPxrKkfm.js +0 -1
  268. package/dist/web/assets/sqlite-viewer-Cs-_D942.js +0 -1
  269. package/dist/web/assets/system-monitor-body-CV7-0hZG.js +0 -2
  270. package/dist/web/assets/system-monitor-tab-Ce-8Axhh.js +0 -1
  271. package/dist/web/assets/system-monitor-window-content-CetwYOQy.js +0 -1
  272. package/dist/web/assets/team-member-sheet-CjgaQjsZ.js +0 -2
  273. package/dist/web/assets/team-member-window-content-DNJiYWS7.js +0 -1
  274. package/dist/web/assets/terminal-tab-DF7521sT.js +0 -3
  275. package/dist/web/assets/tool-cards-DCAXGDJI.js +0 -8
  276. package/dist/web/assets/treemap-KZPCXAKY-Be3KNmns.js +0 -1
  277. package/dist/web/assets/use-open-team-member-H4k74HnV.js +0 -1
  278. package/dist/web/assets/video-preview-B0ZWpX0F.js +0 -1
  279. package/src/web/components/floating-window/default-window-chrome.tsx +0 -71
  280. package/src/web/components/os-explorer/skins/explorer-skin-chrome.tsx +0 -17
  281. /package/dist/web/assets/{abap-MRbmsXOs.js → abap-C6nB04tn.js} +0 -0
  282. /package/dist/web/assets/{actionscript-3-BDDHKqa4.js → actionscript-3-Vx4rw2sC.js} +0 -0
  283. /package/dist/web/assets/{ada-DpuV9KwV.js → ada-Ccd8vM20.js} +0 -0
  284. /package/dist/web/assets/{andromeeda-D6qUCKJo.js → andromeeda-DnBX5xMg.js} +0 -0
  285. /package/dist/web/assets/{apache-CX1NU_Tl.js → apache-B-9_sx0g.js} +0 -0
  286. /package/dist/web/assets/{apex-B4-aoQ3K.js → apex-_wPVBYoL.js} +0 -0
  287. /package/dist/web/assets/{api-client-BSB14J4w.js → api-client-aQb5hHE5.js} +0 -0
  288. /package/dist/web/assets/{applescript-Dm9NI6KR.js → applescript-CcvD-qr0.js} +0 -0
  289. /package/dist/web/assets/{apply-theme-BH_d4amk.js → apply-theme-BeLRfsSu.js} +0 -0
  290. /package/dist/web/assets/{ara-BGN8GAYn.js → ara-C40Ztoms.js} +0 -0
  291. /package/dist/web/assets/{asciidoc-s_yVuR3t.js → asciidoc-CybYkJV4.js} +0 -0
  292. /package/dist/web/assets/{asm-BzQdSvTe.js → asm-9eOKwzR0.js} +0 -0
  293. /package/dist/web/assets/{aurora-x-BJTLETG_.js → aurora-x-B5ZH4t7t.js} +0 -0
  294. /package/dist/web/assets/{awk-BQEGWxvX.js → awk-Dqilob-2.js} +0 -0
  295. /package/dist/web/assets/{ayu-dark-CpTORmLc.js → ayu-dark-CPgRhf5r.js} +0 -0
  296. /package/dist/web/assets/{ayu-light-D8PVj-e6.js → ayu-light-Do06Q52f.js} +0 -0
  297. /package/dist/web/assets/{ayu-mirage-DyElQHtm.js → ayu-mirage-_BhxcrxY.js} +0 -0
  298. /package/dist/web/assets/{ballerina-C82NkRtj.js → ballerina-DDwK54QW.js} +0 -0
  299. /package/dist/web/assets/{bat-0X7DtGI-.js → bat-BGyGlzGk.js} +0 -0
  300. /package/dist/web/assets/{beancount-Xgvy6YRl.js → beancount-CRWBdapI.js} +0 -0
  301. /package/dist/web/assets/{berry-CCT2pZcQ.js → berry-DbSFn2gO.js} +0 -0
  302. /package/dist/web/assets/{bibtex-CpXgZ9M_.js → bibtex-QpsV9gm9.js} +0 -0
  303. /package/dist/web/assets/{bicep-fkeSA62l.js → bicep-CxS8CUve.js} +0 -0
  304. /package/dist/web/assets/{bird2-Co7SeAI8.js → bird2-CuZhQzYR.js} +0 -0
  305. /package/dist/web/assets/{bot-CunPuEdW.js → bot-D6sx11y0.js} +0 -0
  306. /package/dist/web/assets/{c-BpmrTvJh.js → c-9bnDqE3g.js} +0 -0
  307. /package/dist/web/assets/{c3-BZ_Z0RrR.js → c3-JMZTrOhA.js} +0 -0
  308. /package/dist/web/assets/{cadence-B0GBC8OF.js → cadence-DsDNayJS.js} +0 -0
  309. /package/dist/web/assets/{can-open-in-ppm-omBzUBBq.js → can-open-in-ppm-BJfpynya.js} +0 -0
  310. /package/dist/web/assets/{catppuccin-frappe-DIt_xR7m.js → catppuccin-frappe-DYIKXXBe.js} +0 -0
  311. /package/dist/web/assets/{catppuccin-latte-Dw40AcqA.js → catppuccin-latte-IYYOnUJ8.js} +0 -0
  312. /package/dist/web/assets/{catppuccin-macchiato-BJ7DfVEF.js → catppuccin-macchiato-BrJ_7mfS.js} +0 -0
  313. /package/dist/web/assets/{catppuccin-mocha-NI2lfXzU.js → catppuccin-mocha-gzSu7v7-.js} +0 -0
  314. /package/dist/web/assets/{chevron-right-BLOtX8Vy.js → chevron-right-De-Wz5Lz.js} +0 -0
  315. /package/dist/web/assets/{circle-hjUGru6R.js → circle-BCy0AUCo.js} +0 -0
  316. /package/dist/web/assets/{clarity-F39L0xMJ.js → clarity-DLzsC0Hb.js} +0 -0
  317. /package/dist/web/assets/{clock-CvhF4DJP.js → clock-C1CQUQPZ.js} +0 -0
  318. /package/dist/web/assets/{clojure-DloMkd8K.js → clojure-DS1BvoTt.js} +0 -0
  319. /package/dist/web/assets/{cmake-CwerJun_.js → cmake-CDvsJwYp.js} +0 -0
  320. /package/dist/web/assets/{code-DDPoqVri.js → code-DJgYrFzm.js} +0 -0
  321. /package/dist/web/assets/{codeowners-CQyVz4Qf.js → codeowners-BjsYiflJ.js} +0 -0
  322. /package/dist/web/assets/{codeql-Bb229zuY.js → codeql-CG-7ARat.js} +0 -0
  323. /package/dist/web/assets/{common-lisp-KMlIwq5I.js → common-lisp-DSO1Lbh9.js} +0 -0
  324. /package/dist/web/assets/{copy-DKn11Pye.js → copy-BewHj66E.js} +0 -0
  325. /package/dist/web/assets/{coq-DHX_3IIo.js → coq-DYdh3oP_.js} +0 -0
  326. /package/dist/web/assets/{csharp-CEmCZv9Q.js → csharp-DxEBz5s0.js} +0 -0
  327. /package/dist/web/assets/{css-CqZqBD05.js → css-dal3Q-8C.js} +0 -0
  328. /package/dist/web/assets/{csv-l1g_V5MV.js → csv-CpqjMGiA.js} +0 -0
  329. /package/dist/web/assets/{csv-parser-CnS0wqr6.js → csv-parser-3umBA4NY.js} +0 -0
  330. /package/dist/web/assets/{cue-BrxRmilg.js → cue-DinoJ_5k.js} +0 -0
  331. /package/dist/web/assets/{cypher-rZkKwqZc.js → cypher-DzxqmkUW.js} +0 -0
  332. /package/dist/web/assets/{d-BALR-QuP.js → d-BxNwJuEC.js} +0 -0
  333. /package/dist/web/assets/{dark-plus-Cj7rVwh-.js → dark-plus-Clmv3V-0.js} +0 -0
  334. /package/dist/web/assets/{dart-CWQcdkXk.js → dart-BWVtXD35.js} +0 -0
  335. /package/dist/web/assets/{data-grid-types-CYvF-xK5.js → data-grid-types-B4n51Fck.js} +0 -0
  336. /package/dist/web/assets/{database-BH0urvbs.js → database-Y3ESDK4-.js} +0 -0
  337. /package/dist/web/assets/{dax-BNHD-QBA.js → dax-DsImuWgJ.js} +0 -0
  338. /package/dist/web/assets/{desktop-CN0IXPrP.js → desktop-B0jJuG2r.js} +0 -0
  339. /package/dist/web/assets/{diff-BtOXapES.js → diff-CWqAAxoE.js} +0 -0
  340. /package/dist/web/assets/{dist-DB1Oaqcc.js → dist-B-EXdSYE.js} +0 -0
  341. /package/dist/web/assets/{dist-Di6G_5jU.js → dist-C0eNNfbt.js} +0 -0
  342. /package/dist/web/assets/{docker-DNsAo_qO.js → docker-CYFCJdIL.js} +0 -0
  343. /package/dist/web/assets/{dotenv-D6Pl6aOU.js → dotenv-CKDUjURg.js} +0 -0
  344. /package/dist/web/assets/{download-zCATy4x4.js → download-DG3_9xXy.js} +0 -0
  345. /package/dist/web/assets/{dracula-C3m-w12D.js → dracula-CSoPspHE.js} +0 -0
  346. /package/dist/web/assets/{dracula-soft-BYqvXm6Z.js → dracula-soft-BuFjw5L1.js} +0 -0
  347. /package/dist/web/assets/{dream-maker-DZAPbPTi.js → dream-maker-B6PdDRZu.js} +0 -0
  348. /package/dist/web/assets/{emacs-lisp-Ao5SW8ay.js → emacs-lisp-CMcXvD0G.js} +0 -0
  349. /package/dist/web/assets/{everforest-dark-uC8QYotQ.js → everforest-dark-cU8-wYzi.js} +0 -0
  350. /package/dist/web/assets/{everforest-light-CTgsVNMr.js → everforest-light-KhorllqK.js} +0 -0
  351. /package/dist/web/assets/{fennel-WuBw6IR1.js → fennel-BCELZK87.js} +0 -0
  352. /package/dist/web/assets/{file-exclamation-point-COAwgNGw.js → file-exclamation-point-CZ4DiR75.js} +0 -0
  353. /package/dist/web/assets/{fish-Byy9dusu.js → fish-BQc0y_jy.js} +0 -0
  354. /package/dist/web/assets/{fluent-CDxb_sgw.js → fluent-BTINnwF6.js} +0 -0
  355. /package/dist/web/assets/{format-bytes-BE_W3UBg.js → format-bytes-WVcFxJuT.js} +0 -0
  356. /package/dist/web/assets/{fortran-free-form-DKWSTamT.js → fortran-free-form-BQim9wDz.js} +0 -0
  357. /package/dist/web/assets/{gdscript-prYHMgtD.js → gdscript-03w5u8un.js} +0 -0
  358. /package/dist/web/assets/{gdshader-D-RM-SQk.js → gdshader-Dp2daNzU.js} +0 -0
  359. /package/dist/web/assets/{genie-CowkJhej.js → genie-CoNcjPiD.js} +0 -0
  360. /package/dist/web/assets/{gherkin-CLFpoVYJ.js → gherkin-NrPOSPQL.js} +0 -0
  361. /package/dist/web/assets/{github-dark-default-BK_1Qgb8.js → github-dark-default-DOKw-1cI.js} +0 -0
  362. /package/dist/web/assets/{github-dark-dimmed-Cv9lj6f-.js → github-dark-dimmed-DJRNMkEA.js} +0 -0
  363. /package/dist/web/assets/{github-dark-high-contrast-CW5ZgIDh.js → github-dark-high-contrast-Bj7jJ_Gs.js} +0 -0
  364. /package/dist/web/assets/{github-dark-nW2F-RLd.js → github-dark-z4RE9ZqA.js} +0 -0
  365. /package/dist/web/assets/{github-light-D4PqBHGZ.js → github-light-B4k_yMFu.js} +0 -0
  366. /package/dist/web/assets/{github-light-default-B-cHtJJV.js → github-light-default-BHc-Uzhs.js} +0 -0
  367. /package/dist/web/assets/{github-light-high-contrast-Dt0HJq50.js → github-light-high-contrast-CHisIywL.js} +0 -0
  368. /package/dist/web/assets/{gleam-DwSyXJWP.js → gleam-CfbypZ4q.js} +0 -0
  369. /package/dist/web/assets/{gn-Cv5WEzHc.js → gn-YoAjyhJa.js} +0 -0
  370. /package/dist/web/assets/{gnuplot-D7bRdY_M.js → gnuplot-xVkc1f1c.js} +0 -0
  371. /package/dist/web/assets/{go-DiRVJ22U.js → go-GPCwP3Gu.js} +0 -0
  372. /package/dist/web/assets/{groovy-BHAgLTeO.js → groovy-Crh4Yww9.js} +0 -0
  373. /package/dist/web/assets/{gruvbox-dark-hard-C8QZ3gzY.js → gruvbox-dark-hard-BluUFuDS.js} +0 -0
  374. /package/dist/web/assets/{gruvbox-dark-medium-Dp1eeid2.js → gruvbox-dark-medium-Cxk1FWQp.js} +0 -0
  375. /package/dist/web/assets/{gruvbox-dark-soft-Cwq0dWVj.js → gruvbox-dark-soft-CHXMiFmj.js} +0 -0
  376. /package/dist/web/assets/{gruvbox-light-hard-CLQCq2-w.js → gruvbox-light-hard-B6eKPjAD.js} +0 -0
  377. /package/dist/web/assets/{gruvbox-light-medium-APHsh6Mo.js → gruvbox-light-medium-pDwMm1ut.js} +0 -0
  378. /package/dist/web/assets/{gruvbox-light-soft-CX-fYc64.js → gruvbox-light-soft-Cxu6kHqK.js} +0 -0
  379. /package/dist/web/assets/{haskell-C4Tw-TDa.js → haskell-C6JKHjbK.js} +0 -0
  380. /package/dist/web/assets/{haxe-B7fSduTQ.js → haxe-BuBNdF0a.js} +0 -0
  381. /package/dist/web/assets/{hcl-Bi3ho6yC.js → hcl-DZpDdGj2.js} +0 -0
  382. /package/dist/web/assets/{hjson-BXwae2M1.js → hjson-CBkhYRuo.js} +0 -0
  383. /package/dist/web/assets/{hlsl-CRuQLBSa.js → hlsl-C5nMxnp9.js} +0 -0
  384. /package/dist/web/assets/{horizon-DtdQ6qjv.js → horizon-VAFvA6R6.js} +0 -0
  385. /package/dist/web/assets/{horizon-bright-BXSF_uKq.js → horizon-bright-BC0xn7T3.js} +0 -0
  386. /package/dist/web/assets/{houston-C6ASpUjT.js → houston-BxrUivmz.js} +0 -0
  387. /package/dist/web/assets/{hy-BrWBHtHY.js → hy-DLtOXoaH.js} +0 -0
  388. /package/dist/web/assets/{image-gallery-CGvlv8zR.js → image-gallery-Gnf7TdCR.js} +0 -0
  389. /package/dist/web/assets/{imba-C_JJXckG.js → imba-BdpFXM2W.js} +0 -0
  390. /package/dist/web/assets/{ini-DEE_vSHQ.js → ini-BInJO_T0.js} +0 -0
  391. /package/dist/web/assets/{java-CnmpcjcT.js → java-Dxuddnkb.js} +0 -0
  392. /package/dist/web/assets/{javascript-C-M7sa2e.js → javascript-CVamJfLY.js} +0 -0
  393. /package/dist/web/assets/{json-BjZ3dAk6.js → json-BLZ0ozYk.js} +0 -0
  394. /package/dist/web/assets/{json5-BQ2vpqjp.js → json5-BnXzmMKs.js} +0 -0
  395. /package/dist/web/assets/{jsonc-C5MjoWGx.js → jsonc-CSgkSga7.js} +0 -0
  396. /package/dist/web/assets/{jsonl-JvhrmQJI.js → jsonl-CY5W2nF2.js} +0 -0
  397. /package/dist/web/assets/{jsonnet-C5pdZVuo.js → jsonnet-CEJYH3sF.js} +0 -0
  398. /package/dist/web/assets/{jssm-Db17uybX.js → jssm-CsJc7Uhk.js} +0 -0
  399. /package/dist/web/assets/{jsx-tJp2Cyqu.js → jsx-jCiRaHU7.js} +0 -0
  400. /package/dist/web/assets/{kanagawa-dragon-BculT_Y1.js → kanagawa-dragon-DfoA_GxX.js} +0 -0
  401. /package/dist/web/assets/{kanagawa-lotus-yQgHUGwU.js → kanagawa-lotus-BOLYJpWd.js} +0 -0
  402. /package/dist/web/assets/{kanagawa-wave-CyGoWN4d.js → kanagawa-wave-DfKlbT1G.js} +0 -0
  403. /package/dist/web/assets/{kdl-Bn8R1REF.js → kdl-CmssIFTi.js} +0 -0
  404. /package/dist/web/assets/{kotlin-DWughK73.js → kotlin-BRsNgp6x.js} +0 -0
  405. /package/dist/web/assets/{kusto--serPb0x.js → kusto-T8X9jUab.js} +0 -0
  406. /package/dist/web/assets/{laserwave-DfAPJ1tt.js → laserwave-DkJMVJ8Z.js} +0 -0
  407. /package/dist/web/assets/{lean-UAm1HOKl.js → lean-C65KGVPq.js} +0 -0
  408. /package/dist/web/assets/{less-Xj6Ka0fF.js → less-exIPdDlf.js} +0 -0
  409. /package/dist/web/assets/{lib-DgNcCtj3.js → lib-mC1NZfuw.js} +0 -0
  410. /package/dist/web/assets/{libesm-CPh1Av0r.js → libesm-DSutUtl1.js} +0 -0
  411. /package/dist/web/assets/{light-plus-BfS7gPcj.js → light-plus-DiHUXAZt.js} +0 -0
  412. /package/dist/web/assets/{llvm-DvWiVwvU.js → llvm-CJBnEzFM.js} +0 -0
  413. /package/dist/web/assets/{log-Bo5z9bNz.js → log-DxMyUMuP.js} +0 -0
  414. /package/dist/web/assets/{logo-CrIjcMZT.js → logo-CC9NKzca.js} +0 -0
  415. /package/dist/web/assets/{luau-C9TsYwNt.js → luau-Bw10I6zf.js} +0 -0
  416. /package/dist/web/assets/{make-GYq4qVbx.js → make-C_6M90m6.js} +0 -0
  417. /package/dist/web/assets/{markdown-p5mNledS.js → markdown-bR9_R-LF.js} +0 -0
  418. /package/dist/web/assets/{material-theme-CWYOVxsP.js → material-theme-BUx2Qujn.js} +0 -0
  419. /package/dist/web/assets/{material-theme-darker-BDGty7YH.js → material-theme-darker-CRJrPgKm.js} +0 -0
  420. /package/dist/web/assets/{material-theme-lighter-JbgOgV3n.js → material-theme-lighter-CUAYppPa.js} +0 -0
  421. /package/dist/web/assets/{material-theme-ocean-EMOpLpa2.js → material-theme-ocean-DuINF1fg.js} +0 -0
  422. /package/dist/web/assets/{material-theme-palenight-CY5hgm7h.js → material-theme-palenight-W6_icGCj.js} +0 -0
  423. /package/dist/web/assets/{matlab-C-He_NTH.js → matlab-rfqn_b3z.js} +0 -0
  424. /package/dist/web/assets/{mdx-Cr2TR5fj.js → mdx-Bh1B_YOJ.js} +0 -0
  425. /package/dist/web/assets/{mermaid-BYc0-B0U.js → mermaid-Dxf6Ya2k.js} +0 -0
  426. /package/dist/web/assets/{min-dark-CMJwqJqB.js → min-dark-CivZ2L0h.js} +0 -0
  427. /package/dist/web/assets/{min-light-Cx6vFiEX.js → min-light-B1Ykqtma.js} +0 -0
  428. /package/dist/web/assets/{mipsasm-Bjer5HwK.js → mipsasm-DynHaM0d.js} +0 -0
  429. /package/dist/web/assets/{mojo-t90PR-Y2.js → mojo-Clw5PbGH.js} +0 -0
  430. /package/dist/web/assets/{monokai-dci_PdCm.js → monokai-DFIooFZT.js} +0 -0
  431. /package/dist/web/assets/{moonbit-AAzI-Hd-.js → moonbit-DnBSZWGM.js} +0 -0
  432. /package/dist/web/assets/{move-kwBhnhrG.js → move-CCcL2PfL.js} +0 -0
  433. /package/dist/web/assets/{narrat-CXww2YQL.js → narrat-BDarg5Lk.js} +0 -0
  434. /package/dist/web/assets/{nextflow-groovy-CJXsuXGB.js → nextflow-groovy-DrZOeCNW.js} +0 -0
  435. /package/dist/web/assets/{night-owl-_GD204Wr.js → night-owl-BnZZCK7v.js} +0 -0
  436. /package/dist/web/assets/{night-owl-light-DNgkw3kl.js → night-owl-light-CEwBsVHS.js} +0 -0
  437. /package/dist/web/assets/{nix-BgiorKFd.js → nix-amCzOPMR.js} +0 -0
  438. /package/dist/web/assets/{nord-CaBmcxFC.js → nord-BIs2BC6q.js} +0 -0
  439. /package/dist/web/assets/{nushell-DUh4UGx1.js → nushell-Y02fo4yw.js} +0 -0
  440. /package/dist/web/assets/{objective-c-Cl9KU86S.js → objective-c-7xOZtWW1.js} +0 -0
  441. /package/dist/web/assets/{objective-cpp-DVkIA8A0.js → objective-cpp-eVtjUvVB.js} +0 -0
  442. /package/dist/web/assets/{ocaml-vvoHTak0.js → ocaml-Bi6ZwqG4.js} +0 -0
  443. /package/dist/web/assets/{odin-Cyjw8woZ.js → odin-8xf1Y0S9.js} +0 -0
  444. /package/dist/web/assets/{one-dark-pro-B1cviILi.js → one-dark-pro-hVv-_y_b.js} +0 -0
  445. /package/dist/web/assets/{one-light-BPGUJeYI.js → one-light-CJJ3MtHt.js} +0 -0
  446. /package/dist/web/assets/{openscad-BLMdTUU8.js → openscad-B2HcywLk.js} +0 -0
  447. /package/dist/web/assets/{pascal-i5niy3e7.js → pascal-C7fllV_7.js} +0 -0
  448. /package/dist/web/assets/{pkl-CuOV7SsU.js → pkl-qvLC1IWP.js} +0 -0
  449. /package/dist/web/assets/{plastic-Bf_zE5KL.js → plastic-BT1wHZv2.js} +0 -0
  450. /package/dist/web/assets/{plsql-cfqEtMD3.js → plsql-1MsmdmJD.js} +0 -0
  451. /package/dist/web/assets/{plus-BM-Ty0fp.js → plus-BhMZqFsN.js} +0 -0
  452. /package/dist/web/assets/{po-CFJcWgjr.js → po-BigskytD.js} +0 -0
  453. /package/dist/web/assets/{poimandres-G5YoaIFf.js → poimandres-DuklniF7.js} +0 -0
  454. /package/dist/web/assets/{polar-rcjs3i9R.js → polar-e2pjN_sp.js} +0 -0
  455. /package/dist/web/assets/{postcss-CBKY1FTZ.js → postcss-DtAeYjWw.js} +0 -0
  456. /package/dist/web/assets/{powerquery-Db7SXLbO.js → powerquery-Cr2PtehI.js} +0 -0
  457. /package/dist/web/assets/{powershell-LFy3MUTP.js → powershell-BxFTGLJ4.js} +0 -0
  458. /package/dist/web/assets/{prisma-BE8GR1lH.js → prisma-COWJiwdZ.js} +0 -0
  459. /package/dist/web/assets/{prolog-DOn5lR1e.js → prolog-DFvGKRx6.js} +0 -0
  460. /package/dist/web/assets/{proto-wr-TpAK_.js → proto-CcK80lFt.js} +0 -0
  461. /package/dist/web/assets/{puppet-D2Dkv62u.js → puppet-BF60bZ4F.js} +0 -0
  462. /package/dist/web/assets/{purescript-DvgJgPdy.js → purescript-zL_69MzU.js} +0 -0
  463. /package/dist/web/assets/{python-C7TlkHhK.js → python-CIwKhfb_.js} +0 -0
  464. /package/dist/web/assets/{qmldir-CtZMwhcW.js → qmldir-CXNe04Lo.js} +0 -0
  465. /package/dist/web/assets/{qss-dNZ2btnl.js → qss-C8lAWe6G.js} +0 -0
  466. /package/dist/web/assets/{r-BlqnNkHS.js → r-CL5ZVL3_.js} +0 -0
  467. /package/dist/web/assets/{racket-CzRQrGc4.js → racket-BBfh0uh0.js} +0 -0
  468. /package/dist/web/assets/{raku-BwutWhBF.js → raku-o6E8R5Q3.js} +0 -0
  469. /package/dist/web/assets/{react-I_EwPIZi.js → react-CBTnT4sY.js} +0 -0
  470. /package/dist/web/assets/{red-BMXMywmL.js → red-GomRF2Xp.js} +0 -0
  471. /package/dist/web/assets/{reg-BqOKrIOw.js → reg-_ffDIvx9.js} +0 -0
  472. /package/dist/web/assets/{regexp-Bero1BN2.js → regexp-Bl5sF65W.js} +0 -0
  473. /package/dist/web/assets/{rel-BXKWIElA.js → rel-DgMdqDuj.js} +0 -0
  474. /package/dist/web/assets/{resolve-theme-B9ABAH_3.js → resolve-theme-CRt_7wpd.js} +0 -0
  475. /package/dist/web/assets/{riscv-BbbBYJBo.js → riscv-8b3-Ye4X.js} +0 -0
  476. /package/dist/web/assets/{ron-BtVTWW4b.js → ron-DrmU1KHP.js} +0 -0
  477. /package/dist/web/assets/{rose-pine-hvkvQzvU.js → rose-pine-C_-E2tF1.js} +0 -0
  478. /package/dist/web/assets/{rose-pine-dawn-D7lwhUei.js → rose-pine-dawn-DEfhNlFH.js} +0 -0
  479. /package/dist/web/assets/{rose-pine-moon-CoHDmsIw.js → rose-pine-moon-BdvX3gdn.js} +0 -0
  480. /package/dist/web/assets/{rosmsg-CdaZFgI8.js → rosmsg-B6GhGpd5.js} +0 -0
  481. /package/dist/web/assets/{rust-Dy2qsphD.js → rust-DmC97M1-.js} +0 -0
  482. /package/dist/web/assets/{sass-Bz7NVxDb.js → sass-B0tJOHLM.js} +0 -0
  483. /package/dist/web/assets/{save-C4z1p51e.js → save-CtIGOjmx.js} +0 -0
  484. /package/dist/web/assets/{scala-sXSwsNyq.js → scala-n8zaFOXv.js} +0 -0
  485. /package/dist/web/assets/{scheme-DS7TUbN7.js → scheme-BKD9ztBU.js} +0 -0
  486. /package/dist/web/assets/{sdbl-iISFvIep.js → sdbl-D8gB5-rS.js} +0 -0
  487. /package/dist/web/assets/{shellscript-BkIl4ApC.js → shellscript-BfXlf_Ao.js} +0 -0
  488. /package/dist/web/assets/{shield-check-C5laObJv.js → shield-check-B0iGUiOK.js} +0 -0
  489. /package/dist/web/assets/{shield-off-DULFtyLS.js → shield-off-BNLWBhcq.js} +0 -0
  490. /package/dist/web/assets/{slack-dark-B1eg0_m2.js → slack-dark-CylEddse.js} +0 -0
  491. /package/dist/web/assets/{slack-ochin-mdkc1ldu.js → slack-ochin-w8wg8vuC.js} +0 -0
  492. /package/dist/web/assets/{smalltalk-CORtd03t.js → smalltalk-hiAXA64u.js} +0 -0
  493. /package/dist/web/assets/{snazzy-light-Bc6Q2G89.js → snazzy-light-BwlV3Xty.js} +0 -0
  494. /package/dist/web/assets/{solarized-dark-CF83zRXM.js → solarized-dark-vmNGdykz.js} +0 -0
  495. /package/dist/web/assets/{solarized-light-BoKQZaYU.js → solarized-light-DGv_0JXq.js} +0 -0
  496. /package/dist/web/assets/{solidity-DOgi1N4w.js → solidity-Y7QSH0B1.js} +0 -0
  497. /package/dist/web/assets/{sparkles-Dqsf3hq6.js → sparkles-Dh-_J2Rd.js} +0 -0
  498. /package/dist/web/assets/{splunk-BXfw5ZLy.js → splunk-BtgpLjHi.js} +0 -0
  499. /package/dist/web/assets/{sql-BcVs-eX4.js → sql-CRHYhOia.js} +0 -0
  500. /package/dist/web/assets/{ssh-config-CLCtNkkd.js → ssh-config-DOqSs3au.js} +0 -0
  501. /package/dist/web/assets/{stylus-DdP992aO.js → stylus-crCAEaBT.js} +0 -0
  502. /package/dist/web/assets/{swift-BnGb6Lgc.js → swift-eE3rT7TC.js} +0 -0
  503. /package/dist/web/assets/{synthwave-84-cg9264l9.js → synthwave-84-BWy14LBX.js} +0 -0
  504. /package/dist/web/assets/{system-verilog-GbHpszs3.js → system-verilog-DC0-DZM4.js} +0 -0
  505. /package/dist/web/assets/{systemd-Dz-bNsDQ.js → systemd-to5p6N8I.js} +0 -0
  506. /package/dist/web/assets/{table-CHmxuh6M.js → table-Bbc783ko.js} +0 -0
  507. /package/dist/web/assets/{talonscript-CFIidoBA.js → talonscript-DoTcU8wm.js} +0 -0
  508. /package/dist/web/assets/{tasl-Cu-TRTKx.js → tasl-cNZvUs95.js} +0 -0
  509. /package/dist/web/assets/{tcl-DwCHCB1K.js → tcl-mZE8sZH8.js} +0 -0
  510. /package/dist/web/assets/{terraform-BzZw4T1z.js → terraform-CqHPpIfu.js} +0 -0
  511. /package/dist/web/assets/{tokyo-night-RKsj2-tv.js → tokyo-night-Tp2rTIZd.js} +0 -0
  512. /package/dist/web/assets/{toml-CirbOgDP.js → toml-CU_vscgn.js} +0 -0
  513. /package/dist/web/assets/{tsv-CraRcWdU.js → tsv-ik7iFB9D.js} +0 -0
  514. /package/dist/web/assets/{tsx-CjFg0lgw.js → tsx-BMvvMKiv.js} +0 -0
  515. /package/dist/web/assets/{turtle-B-WBIOa6.js → turtle-DBqKCq9o.js} +0 -0
  516. /package/dist/web/assets/{typescript-MpLarYn1.js → typescript-DXJDmMZZ.js} +0 -0
  517. /package/dist/web/assets/{typespec-B7QlHMZ_.js → typespec-CBseCMtZ.js} +0 -0
  518. /package/dist/web/assets/{typst-CcHSKFZj.js → typst-4oY25U9y.js} +0 -0
  519. /package/dist/web/assets/{use-is-mobile-BXGVvczu.js → use-is-mobile-D1weanbj.js} +0 -0
  520. /package/dist/web/assets/{utils-DoY4yTP-.js → utils-BNRH507E.js} +0 -0
  521. /package/dist/web/assets/{v-xTGhWZuD.js → v-BXaZ_1oy.js} +0 -0
  522. /package/dist/web/assets/{vala-DwebjH3H.js → vala-BImWJE7z.js} +0 -0
  523. /package/dist/web/assets/{vb-BxJT2RAy.js → vb-CLfj2_sy.js} +0 -0
  524. /package/dist/web/assets/{vendor-xterm-CU6zIYMB.js → vendor-xterm-_yyu5n32.js} +0 -0
  525. /package/dist/web/assets/{verilog-CvV6RHPD.js → verilog-BWa8Ed2b.js} +0 -0
  526. /package/dist/web/assets/{vesper-CY3qd7E_.js → vesper-BGj1cg6m.js} +0 -0
  527. /package/dist/web/assets/{vhdl-B9ZX-sUL.js → vhdl-mByK7mlx.js} +0 -0
  528. /package/dist/web/assets/{viml-Y42h_ExQ.js → viml-CugmlW5g.js} +0 -0
  529. /package/dist/web/assets/{vitesse-black-DkXP6Sv-.js → vitesse-black-vPdpy9TL.js} +0 -0
  530. /package/dist/web/assets/{vitesse-dark-B9CkIB6r.js → vitesse-dark-BuQK3dUh.js} +0 -0
  531. /package/dist/web/assets/{vitesse-light-C7DHrJCK.js → vitesse-light-B3nz1XL9.js} +0 -0
  532. /package/dist/web/assets/{vyper-Cnd9s5j-.js → vyper-DH_GTIHG.js} +0 -0
  533. /package/dist/web/assets/{wasm-DQE71XTB.js → wasm-C-LF9GjX.js} +0 -0
  534. /package/dist/web/assets/{wasm-iWe7Fzjc.js → wasm-DfVbVJlW.js} +0 -0
  535. /package/dist/web/assets/{wenyan-Bc5Pnm9l.js → wenyan-CzQkHyHx.js} +0 -0
  536. /package/dist/web/assets/{wgsl-D-YUAWkP.js → wgsl-Du_M1DW9.js} +0 -0
  537. /package/dist/web/assets/{wikitext-DYQDUYf2.js → wikitext-BWN_w5S7.js} +0 -0
  538. /package/dist/web/assets/{wit-P6u7mfwy.js → wit-BR13v5HD.js} +0 -0
  539. /package/dist/web/assets/{wolfram-6SXLUqao.js → wolfram-BoXxp_Xl.js} +0 -0
  540. /package/dist/web/assets/{x-BcqfTY_7.js → x-nhriOX9o.js} +0 -0
  541. /package/dist/web/assets/{yaml-CQiMLVcZ.js → yaml-DpR_EF-d.js} +0 -0
  542. /package/dist/web/assets/{zenscript-DFMywo_P.js → zenscript-C-EdUtUd.js} +0 -0
  543. /package/dist/web/assets/{zig-CtAjaIiF.js → zig-BD4eA5nU.js} +0 -0
@@ -2264,10 +2264,87 @@ below the app's existing `z-40` click-away backdrops and `z-50` Radix layers, so
2264
2264
  dropdowns and dialogs always stay reachable above any number of open explorer windows. Below the
2265
2265
  `md` breakpoint the layer never mounts at all; `src/web/components/os-explorer/mobile/` renders the
2266
2266
  same `ExplorerBody` component inside a full-screen bottom sheet instead (`variant="sheet"`).
2267
-
2268
- A window's titlebar is a swappable `chrome` component (`WindowChromeProps` contract) the OS skin
2269
- picks Windows caption buttons or macOS traffic lights from `src/web/components/os-explorer/skins/`,
2270
- scoped entirely through `[data-skin="windows"|"macos"]` CSS variables layered over PPM's existing
2271
- semantic theme tokens, so both PPM dark and light mode render correctly under either skin with no
2272
- second color table.
2267
+ Drag and resize share a `gestureAbandoned()` guard (`use-window-gesture-context.ts`) for the
2268
+ pointer-up that still arrives after a mid-gesture window close (e.g. dragging by a titlebar button
2269
+ that closes the frame).
2270
+
2271
+ **One chrome, every kind.** `WindowSkinChrome` (`window-skin-chrome.tsx`) is the titlebar every
2272
+ window kind — explorer, team-member session, system monitor, detached tab — renders: it resolves
2273
+ the active OS skin via `useExplorerSkin()` (Settings override, else host platform; Linux → macOS)
2274
+ and delegates to that skin's `WindowsWindowChrome` / `MacosWindowChrome`
2275
+ (`src/web/components/os-explorer/skins/`), scoped entirely through `[data-skin="windows"|"macos"]`
2276
+ CSS variables layered over PPM's existing semantic theme tokens — no second color table. The
2277
+ Windows skin's folder glyph draws only for `kind === "explorer"`; every other kind gets the bare
2278
+ titlebar. The macOS skin boxes the title between the traffic lights and the PiP button as a flex
2279
+ child (so a long title truncates instead of overlapping either), and puts the PiP button at the
2280
+ titlebar's right end; the Windows skin puts it left of minimize.
2281
+
2282
+ **PiP is a capability of the frame, not of one kind.** `useWindowBodyElement`
2283
+ (`use-window-body-element.ts`) creates the single DOM element `FloatingWindow` portals a window's
2284
+ content into and publishes it as that window's PiP slot (`window-pip-registry.ts`, keyed by window
2285
+ id). `PipCaptionButton` (`pip/pip-caption-button.tsx`), rendered by both skins, moves that slot into
2286
+ a `documentPictureInPicture` window and back; it is absent (not disabled) where the API is
2287
+ unsupported. `WindowPipPlaceholder` (`window-pip-placeholder.tsx`) takes the body's place in the
2288
+ frame while it plays in PiP, with a ≥44px "Bring back" control. The mechanics below (attach/detach,
2289
+ style mirroring, key forwarding, resize signalling) apply to whichever window kind currently owns
2290
+ the slot — a tab-host window is only the one kind whose body is itself a portal target for another
2291
+ component (`TabPool`).
2292
+
2293
+ #### Tab-host windows (detaching a tab into its own window)
2294
+
2295
+ - **Off-grid panel.** Detaching creates `` `__win__:${windowId}` `` (`windowPanelId()`,
2296
+ `stores/panel-utils.ts`) — same treatment as `__dock__`: lives in `panels`, never in `grid`, so no
2297
+ grid math (rows/columns/split) sees it. `stores/window-panel-actions.ts` is the only writer of
2298
+ these panels and enforces the paired invariant: `focusedPanelId` never points at one (it would
2299
+ send the next `openTab()` with no explicit panel into a window). `popOutTab`/`redockFromWindow`
2300
+ create and destroy the panel and its window together; every close path (titlebar ×, keyboard,
2301
+ reconcile) routes through `redockFromWindow`, which re-docks to the origin panel if it is still in
2302
+ the grid, else the focused grid panel, else the first grid panel. All tab types pop out except
2303
+ `system-monitor`, which already has its own window kind.
2304
+ - **No-remount move.** `TabPool` (`components/layout/tab-pool.tsx`) mounts every tab once into a
2305
+ wrapper `div[data-tab-pool-id]` created imperatively in `ReparentingTab`
2306
+ (`components/layout/reparenting-tab.tsx`) and rendered into it via `createPortal` — React attaches
2307
+ its listeners to the wrapper itself, so they keep firing after the node moves, including into
2308
+ another document. A `useLayoutEffect` with no deps calls `appendChild` to move the wrapper into
2309
+ whichever element last registered for the tab's panel id (`slotRegistry`,
2310
+ `components/layout/tab-pool-registry.ts`); `TabHostWindowContent`'s slot `div` is always mounted
2311
+ (never swapped for a placeholder), because it may currently be living inside the PiP document.
2312
+ - **Persistence.** Window panels persist to their own global `localStorage["ppm-window-panels"]`
2313
+ key (`stores/window-panel-persistence.ts`), separate from the per-project `ppm-panels-*` blob and
2314
+ not synced to the server — the same limitation window geometry (`ppm-windows`) already has.
2315
+ `WINDOW_KINDS` (`window-store-types.ts`) is the single list both the window store and
2316
+ `window-persistence.ts` filter against; `team-member` is excluded from restore because its body
2317
+ streams a live subagent session that cannot survive a reload.
2318
+ - **Reconcile.** The two halves persist separately, so a reload can restore one without the other.
2319
+ `reconcileTabHostWindows` (`stores/window-panel-reconcile.ts`), run once per project via
2320
+ `useWindowPanelReconcile()` after the window layer restores, and unconditionally below `md` (the
2321
+ window layer never mounts there): a panel whose window is gone comes back to the grid; a window
2322
+ with no panel behind it closes.
2323
+ - **PiP host.** `attachPipHost`/`isDocumentPipSupported` (`floating-window/pip/pip-host.ts`,
2324
+ `pip-support.ts`) move a window's *slot* element — never a tab's own wrapper — into a
2325
+ `documentPictureInPicture` window, one at a time per page. `pagehide` triggers a synchronous
2326
+ restore (no `await` between it and the DOM move) so a closing PiP document never strips listeners
2327
+ off a still-live terminal. `pip-style-copy.ts` mirrors stylesheets + `adoptedStyleSheets` once and
2328
+ `<html>` class/inline theme CSS vars + `<body>` class **and inline style** on every theme change
2329
+ (the page background is an inline `background: var(--bg)` on `<body>` in `index.html`, not a
2330
+ class), plus a MutationObserver for Vite HMR-injected `<style>` tags. `pip-key-forward.ts`
2331
+ re-dispatches keydown/keyup from the PiP window onto the main window for app-level shortcuts,
2332
+ skipping targets that own their own input (`input`, `.monaco-editor`, `.xterm-helper-textarea`,
2333
+ etc.). `pip-resize-signal.ts` dispatches a non-bubbling `ppm:host-resize` CustomEvent on each
2334
+ `[data-tab-pool-id]` wrapper inside the slot (on attach, every PiP `resize`, and on detach); the
2335
+ terminal and editors subscribe via `onHostResize` and re-fit, because main-window
2336
+ `ResizeObserver`s are late or silent for a PiP-driven size.
2337
+ - **Radix portals in PiP.** `PortalContainerProvider` (`components/ui/portal-container-context.tsx`)
2338
+ is mounted inside `ReparentingTab` around each tab's content, fed the PiP document's `body` while
2339
+ that tab's window is in PiP (`usePipPortalContainer`, `window-pip-registry.ts`) — so a tab's own
2340
+ dropdowns/tooltips/dialogs render inside the PiP document instead of opening unreachably in the
2341
+ main window. `undefined` (document default) while docked.
2342
+ - **Known limitations** (see the comment block atop `pip/pip-caption-button.tsx`): sonner toasts
2343
+ always render in the main window (one app-root toaster); `useIsMobile()`/Tailwind `md:` read the
2344
+ main window's viewport, not the PiP window's; `onSelect`/`selectionchange` degrades for PiP
2345
+ content; the terminal's reconnect check reads the main document's visibility; Monaco keybindings
2346
+ (Ctrl+Z, Ctrl+F, …) don't fire while the editor sits in PiP (typing still reaches the buffer); a
2347
+ tab-host window's titlebar keeps the tab title captured at pop-out time.
2348
+ - **Mobile.** Pop-out and PiP are hidden entirely below `md` (`useIsMobile()`) — never a scaled-down
2349
+ window.
2273
2350
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hienlh/ppm",
3
- "version": "0.18.10",
3
+ "version": "0.18.12",
4
4
  "description": "Personal Project Manager — mobile-first web IDE with AI assistance",
5
5
  "author": "hienlh",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -77,8 +77,11 @@ export function FilePicker({
77
77
  const handler = (e: globalThis.KeyboardEvent) => {
78
78
  if (handleKeyDown(e)) e.stopPropagation();
79
79
  };
80
- document.addEventListener("keydown", handler, true);
81
- return () => document.removeEventListener("keydown", handler, true);
80
+ // The list's own document in a picture-in-picture window the keys are
81
+ // delivered there, not to the main document.
82
+ const doc = listRef.current?.ownerDocument ?? document;
83
+ doc.addEventListener("keydown", handler, true);
84
+ return () => doc.removeEventListener("keydown", handler, true);
82
85
  }, [visible, handleKeyDown]);
83
86
 
84
87
  if (!visible || filtered.length === 0) return null;
@@ -39,8 +39,11 @@ export function ModeSelector({ value, onChange, open, onOpenChange }: ModeSelect
39
39
  onOpenChange(false);
40
40
  }
41
41
  };
42
- document.addEventListener("mousedown", handler);
43
- return () => document.removeEventListener("mousedown", handler);
42
+ // The panel's own document — in a picture-in-picture window the main
43
+ // document never sees these clicks, so the panel would never close.
44
+ const doc = panelRef.current?.ownerDocument ?? document;
45
+ doc.addEventListener("mousedown", handler);
46
+ return () => doc.removeEventListener("mousedown", handler);
44
47
  }, [open, onOpenChange]);
45
48
 
46
49
  // Focus current mode on open
@@ -50,8 +50,11 @@ export function ModelSelector({ value, onChange, projectName, providerId, disabl
50
50
  setOpen(false);
51
51
  }
52
52
  };
53
- document.addEventListener("mousedown", handler);
54
- return () => document.removeEventListener("mousedown", handler);
53
+ // The panel's own document — in a picture-in-picture window the main
54
+ // document never sees these clicks, so the panel would never close.
55
+ const doc = panelRef.current?.ownerDocument ?? document;
56
+ doc.addEventListener("mousedown", handler);
57
+ return () => doc.removeEventListener("mousedown", handler);
55
58
  }, [open]);
56
59
 
57
60
  // Focus current on open
@@ -69,8 +69,11 @@ export function ModelThinkingSelector({
69
69
  const handler = (e: MouseEvent) => {
70
70
  if (panelRef.current && !panelRef.current.contains(e.target as Node)) setOpen(false);
71
71
  };
72
- document.addEventListener("mousedown", handler);
73
- return () => document.removeEventListener("mousedown", handler);
72
+ // The panel's own document — in a picture-in-picture window the main
73
+ // document never sees these clicks, so the panel would never close.
74
+ const doc = panelRef.current?.ownerDocument ?? document;
75
+ doc.addEventListener("mousedown", handler);
76
+ return () => doc.removeEventListener("mousedown", handler);
74
77
  }, [open, isMobile]);
75
78
 
76
79
  const current = models.find((m) => m.value === model);
@@ -45,8 +45,11 @@ export function ProviderSelector({ value, onChange, projectName }: ProviderSelec
45
45
  setOpen(false);
46
46
  }
47
47
  };
48
- document.addEventListener("mousedown", handler);
49
- return () => document.removeEventListener("mousedown", handler);
48
+ // The panel's own document — in a picture-in-picture window the main
49
+ // document never sees these clicks, so the panel would never close.
50
+ const doc = panelRef.current?.ownerDocument ?? document;
51
+ doc.addEventListener("mousedown", handler);
52
+ return () => doc.removeEventListener("mousedown", handler);
50
53
  }, [open]);
51
54
 
52
55
  // Focus current on open
@@ -117,8 +117,11 @@ export function SlashCommandPicker({
117
117
  const handler = (e: globalThis.KeyboardEvent) => {
118
118
  if (handleKeyDown(e)) e.stopPropagation();
119
119
  };
120
- document.addEventListener("keydown", handler, true);
121
- return () => document.removeEventListener("keydown", handler, true);
120
+ // The list's own document in a picture-in-picture window the keys are
121
+ // delivered there, not to the main document.
122
+ const doc = listRef.current?.ownerDocument ?? document;
123
+ doc.addEventListener("keydown", handler, true);
124
+ return () => doc.removeEventListener("keydown", handler, true);
122
125
  }, [visible, handleKeyDown]);
123
126
 
124
127
  const handleRefresh = useCallback(() => {
@@ -22,6 +22,7 @@ import type { DbQueryResult } from "../database/use-database";
22
22
  // Single source of truth: the explorer decides whether a double-click can open a file at
23
23
  // all from these very sets, so they must not be redeclared here.
24
24
  import { AUDIO_EXTS, IMAGE_EXTS, SQLITE_EXTS, VIDEO_EXTS } from "@/components/os-explorer/can-open-in-ppm";
25
+ import { onHostResize } from "@/components/floating-window/pip/pip-resize-signal";
25
26
 
26
27
  const MarkdownRenderer = lazy(() =>
27
28
  import("@/components/shared/markdown-renderer").then((m) => ({ default: m.MarkdownRenderer }))
@@ -247,6 +248,12 @@ export const CodeEditor = memo(function CodeEditor({ metadata, tabId }: CodeEdit
247
248
  };
248
249
  }, [isMobile]);
249
250
 
251
+ // Host-driven resize (picture-in-picture): `automaticLayout` never fires for
252
+ // a size driven by another document, and after the return the editor keeps
253
+ // the PiP size until it is told to lay out again.
254
+ // Re-runs on loading/error because the container only exists once the file rendered.
255
+ useEffect(() => onHostResize(containerRef.current, () => editorRef.current?.layout()), [loading, error]);
256
+
250
257
  // CodeLens: inline Run buttons between SQL statements
251
258
  const codeLensDisposable = useRef<MonacoType.IDisposable[]>([]);
252
259
  const runSqlRef = useRef(runSqlInViewer);
@@ -820,10 +827,13 @@ function SqlResultPanel({ result, error, loading, connName, onClose, onOpenInTab
820
827
  e.preventDefault();
821
828
  const startY = e.clientY;
822
829
  const startH = panelHeight;
830
+ // The handle's own document — the editor may be living in a PiP window,
831
+ // where the main document never sees these pointer events.
832
+ const doc = e.currentTarget.ownerDocument;
823
833
  const onMove = (ev: MouseEvent) => setPanelHeight(Math.max(80, startH + (startY - ev.clientY)));
824
- const onUp = () => { document.removeEventListener("mousemove", onMove); document.removeEventListener("mouseup", onUp); };
825
- document.addEventListener("mousemove", onMove);
826
- document.addEventListener("mouseup", onUp);
834
+ const onUp = () => { doc.removeEventListener("mousemove", onMove); doc.removeEventListener("mouseup", onUp); };
835
+ doc.addEventListener("mousemove", onMove);
836
+ doc.addEventListener("mouseup", onUp);
827
837
  }, [panelHeight]);
828
838
 
829
839
  return (
@@ -5,6 +5,7 @@ import { api, projectUrl } from "@/lib/api-client";
5
5
  import { useShallow } from "zustand/react/shallow";
6
6
  import { useSettingsStore } from "@/stores/settings-store";
7
7
  import { useMonacoTheme } from "@/lib/use-monaco-theme";
8
+ import { onHostResize } from "@/components/floating-window/pip/pip-resize-signal";
8
9
  import { Loader2 } from "lucide-react";
9
10
 
10
11
  function getMonacoLanguage(filename: string): string {
@@ -117,6 +118,14 @@ export function ConflictEditor({ metadata }: ConflictEditorProps) {
117
118
  return () => ro.disconnect();
118
119
  }, []);
119
120
 
121
+ // Host-driven resize (picture-in-picture): `automaticLayout` never fires for a
122
+ // size driven by another document, and the editor keeps the PiP size after the
123
+ // return. Re-runs on loading/error because the container renders only then.
124
+ useEffect(
125
+ () => onHostResize(containerRef.current, () => editorRef.current?.layout()),
126
+ [loading, error],
127
+ );
128
+
120
129
  // Load file content
121
130
  useEffect(() => {
122
131
  if (!filePath || !projectName) return;
@@ -4,6 +4,7 @@ import { api, projectUrl } from "@/lib/api-client";
4
4
  import { useShallow } from "zustand/react/shallow";
5
5
  import { useSettingsStore } from "@/stores/settings-store";
6
6
  import { useMonacoTheme } from "@/lib/use-monaco-theme";
7
+ import { onHostResize } from "@/components/floating-window/pip/pip-resize-signal";
7
8
  import { Loader2, FileCode, WrapText } from "lucide-react";
8
9
 
9
10
  function getMonacoLanguage(filename: string): string {
@@ -60,6 +61,14 @@ export function DiffViewer({ metadata }: DiffViewerProps) {
60
61
  return () => ro.disconnect();
61
62
  }, [loading, error]);
62
63
 
64
+ // Host-driven resize (picture-in-picture): `automaticLayout` never fires for a
65
+ // size driven by another document, and the editor keeps the PiP size after the
66
+ // return. Re-runs on loading/error because the container renders only then.
67
+ useEffect(
68
+ () => onHostResize(containerRef.current, () => diffEditorRef.current?.layout()),
69
+ [loading, error],
70
+ );
71
+
63
72
  useEffect(() => {
64
73
  if (isInline) return;
65
74
  if (!projectName) return;
@@ -1,16 +1,25 @@
1
1
  /**
2
- * One floating window: geometry, gestures, keyboard, and a chrome slot.
2
+ * One floating window: geometry, gestures, keyboard, the skinned chrome, and the body
3
+ * element every kind renders into.
3
4
  *
4
5
  * Geometry is written straight to the element instead of through React state — a drag emits
5
6
  * a pointermove per frame and re-rendering the window (and its content) on each one is what
6
7
  * makes a window manager feel heavy. The store is written only when a gesture ends, which is
7
8
  * also the moment the rect is rounded to whole pixels.
9
+ *
10
+ * Picture-in-picture is a capability of the FRAME, not of any one kind: the body element is
11
+ * published as this window's PiP slot, so an explorer, a system monitor, a team-member
12
+ * session and a detached tab all pop out through the same titlebar button.
8
13
  */
9
14
 
10
15
  import { useCallback, useLayoutEffect, useRef, useState, type ReactNode } from "react";
16
+ import { createPortal } from "react-dom";
11
17
  import { cn } from "@/lib/utils";
12
- import { DefaultWindowChrome } from "./default-window-chrome";
13
- import { TITLEBAR_HEIGHT, type WindowChrome } from "./window-chrome-contract";
18
+ import { PortalContainerProvider } from "@/components/ui/portal-container-context";
19
+ import { TITLEBAR_HEIGHT } from "./window-chrome-contract";
20
+ import { useWindowBodyElement } from "./use-window-body-element";
21
+ import { WindowPipPlaceholder } from "./window-pip-placeholder";
22
+ import { WindowSkinChrome } from "./window-skin-chrome";
14
23
  import { windowZIndex, type Bounds, type Rect } from "./window-geometry";
15
24
  import { useWindowStore, type WindowRuntimeState } from "./window-store";
16
25
  import { useWindowDrag } from "./use-window-drag";
@@ -28,8 +37,6 @@ export interface FloatingWindowProps {
28
37
  getScale: () => number;
29
38
  /** Told when a gesture starts/ends so the layer can raise its capture overlay. */
30
39
  onGestureActive: (active: boolean) => void;
31
- /** Skin component for the titlebar; owns its own hooks and state. */
32
- chrome?: WindowChrome;
33
40
  children: ReactNode;
34
41
  }
35
42
 
@@ -47,7 +54,6 @@ export function FloatingWindow({
47
54
  focused,
48
55
  getScale,
49
56
  onGestureActive,
50
- chrome,
51
57
  children,
52
58
  }: FloatingWindowProps) {
53
59
  const rootRef = useRef<HTMLDivElement>(null);
@@ -57,6 +63,8 @@ export function FloatingWindow({
57
63
  const minimized = win.state === "minimized";
58
64
  const rect: Rect = maximized ? { x: 0, y: 0, w: bounds.w, h: bounds.h } : win.rect;
59
65
 
66
+ const { body, pip } = useWindowBodyElement(win.id, rootRef, minimized);
67
+
60
68
  // Latest committed geometry, read at the first frame of a gesture (never mid-gesture,
61
69
  // where it would compound the cumulative movement).
62
70
  const rectRef = useRef(rect);
@@ -112,8 +120,6 @@ export function FloatingWindow({
112
120
  movable: !maximized,
113
121
  });
114
122
 
115
- const Chrome = chrome ?? DefaultWindowChrome;
116
-
117
123
  return (
118
124
  <div
119
125
  ref={rootRef}
@@ -131,7 +137,7 @@ export function FloatingWindow({
131
137
  gesturing ? "transition-none" : "transition-[transform,width,height] duration-150 motion-reduce:transition-none",
132
138
  )}
133
139
  >
134
- <Chrome
140
+ <WindowSkinChrome
135
141
  id={win.id}
136
142
  kind={win.kind}
137
143
  title={title}
@@ -152,16 +158,18 @@ export function FloatingWindow({
152
158
  onClose={close}
153
159
  />
154
160
 
155
-
156
- {/* Always mounted, even minimized — content owns per-window state (explorer history,
157
- selection, filter) that a remount would wipe. Hidden via CSS, not unmounted. */}
158
- <div className={cn("relative flex-1 min-h-0 overflow-hidden rounded-b-[8px] bg-panel", minimized && "hidden")}>
159
- {children}
160
- </div>
161
+ {pip && <WindowPipPlaceholder pip={pip} minimized={minimized} />}
161
162
 
162
163
  {!maximized && !minimized && (
163
164
  <WindowResizeHandles bind={(handle) => bindResize(handle) as Record<string, unknown>} />
164
165
  )}
166
+
167
+ {/* Radix primitives inside the content must portal into whichever document the body
168
+ currently lives in; `undefined` (never `null`) restores the document default. */}
169
+ {createPortal(
170
+ <PortalContainerProvider container={pip?.pipWindow.document.body}>{children}</PortalContainerProvider>,
171
+ body,
172
+ )}
165
173
  </div>
166
174
  );
167
175
  }
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Titlebar button that moves a floating window's body into a Document Picture-in-Picture
3
+ * window and back. Every skin renders it, so every window kind gets the capability — the
4
+ * skin only supplies the box (`className`) that matches its own caption metric.
5
+ *
6
+ * The button is absent, never disabled, where the API is missing (Firefox, Safari, any
7
+ * non-secure context) — a caption button that only ever explains itself is worse than no
8
+ * button at all.
9
+ *
10
+ * Known limitations while a window's body runs in PiP; expected behaviour, not regressions:
11
+ * - Toasts render in the main window. Sonner mounts one toaster at the app root and it
12
+ * stays there, so a message raised from the PiP body appears behind it.
13
+ * - `useIsMobile()` and Tailwind `md:` variants read the MAIN window's viewport, so the
14
+ * content keeps its desktop layout in a narrow PiP window instead of switching to mobile.
15
+ * - React's `onSelect`/`selectionchange` is delegated from the document the app root is
16
+ * mounted in; selection-driven UI degrades for content living in the PiP document.
17
+ * - `use-terminal`'s reconnect check reads the main document's visibility, so a hidden
18
+ * main tab is treated as hidden even while its terminal is visible in PiP.
19
+ * - Monaco chords (Ctrl+Z, Ctrl+F, …) do not fire while the editor sits in PiP: typing
20
+ * reaches the buffer, but the keybinding dispatcher listens on the window the editor was
21
+ * created in. Undo works again as soon as the body is brought back.
22
+ * - A tab-host titlebar shows the tab title captured at pop-out time; a tab renamed
23
+ * afterwards (a chat acquiring a name) keeps the old caption until it is popped out again.
24
+ */
25
+
26
+ import { PictureInPicture2 } from "lucide-react";
27
+ import { toast } from "sonner";
28
+ import { cn } from "@/lib/utils";
29
+ import { TITLEBAR_HEIGHT } from "../window-chrome-contract";
30
+ import { useWindowStore } from "../window-store";
31
+ import { setWindowPip, windowPip, windowSlot, useWindowPip } from "../window-pip-registry";
32
+ import { activePipHost, attachPipHost } from "./pip-host";
33
+ import { focusPipDocument } from "./pip-focus-target";
34
+ import { isDocumentPipSupported } from "./pip-support";
35
+
36
+ export interface PipCaptionButtonProps {
37
+ /** Window id — the registry key for both the body element and the resulting handle. */
38
+ id: string;
39
+ /** The skin's caption-button box. Defaults to a compact icon button. */
40
+ className?: string;
41
+ }
42
+
43
+ const DEFAULT_BOX =
44
+ "grid place-items-center size-6 rounded text-text-2 can-hover:hover:bg-surface-elevated can-hover:hover:text-text transition-colors";
45
+
46
+ export function PipCaptionButton({ id, className }: PipCaptionButtonProps) {
47
+ const pip = useWindowPip(id);
48
+
49
+ if (!isDocumentPipSupported()) return null;
50
+
51
+ const togglePip = () => {
52
+ const active = windowPip(id);
53
+ if (active) {
54
+ active.detach();
55
+ return;
56
+ }
57
+
58
+ const slot = windowSlot(id);
59
+ if (!slot) {
60
+ toast.error("This window has nothing to pop out yet");
61
+ return;
62
+ }
63
+ const rect = useWindowStore.getState().windows[id]?.rect;
64
+
65
+ // attachPipHost() is the first call that can consume the click's transient
66
+ // activation; anything awaited before it costs the gesture and the request is
67
+ // rejected. Only synchronous store/registry reads may precede it. The PiP window
68
+ // shows the body alone, so the titlebar comes off the requested height.
69
+ attachPipHost(slot, {
70
+ // A zero falls through to the host's minimum size rather than a magic default.
71
+ width: rect?.w ?? 0,
72
+ height: rect ? rect.h - TITLEBAR_HEIGHT : 0,
73
+ onDetach: () => setWindowPip(id, null),
74
+ })
75
+ .then((handle) => {
76
+ // The window can be closed before this resolves, in which case onDetach has
77
+ // already cleared the state and storing the handle would strand a dead one.
78
+ // A null handle is that same case, detected inside the host. The slot check
79
+ // covers a body that unmounted and came back: the new one is not this one.
80
+ if (!handle || activePipHost() !== handle) return;
81
+ if (windowSlot(id) !== slot) {
82
+ handle.detach();
83
+ return;
84
+ }
85
+ setWindowPip(id, handle);
86
+ // A DOM move carries no focus with it: without this the popped-out terminal or
87
+ // editor is visible but swallows nothing until the user clicks it.
88
+ focusPipDocument(handle.pipWindow.document);
89
+ })
90
+ .catch(() => {
91
+ toast.error("Could not open the picture-in-picture window");
92
+ });
93
+ };
94
+
95
+ const label = pip ? "Bring back from picture-in-picture" : "Open in picture-in-picture";
96
+ return (
97
+ <button
98
+ type="button"
99
+ title={label}
100
+ aria-label={label}
101
+ aria-pressed={Boolean(pip)}
102
+ className={cn(className ?? DEFAULT_BOX, pip && "text-primary")}
103
+ onClick={togglePip}
104
+ >
105
+ <PictureInPicture2 className="size-3.5" />
106
+ </button>
107
+ );
108
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Picks what to focus inside a freshly opened PiP window.
3
+ *
4
+ * Moving a subtree into another document does not move focus with it, so a popped-out
5
+ * terminal or editor would sit there swallowing nothing until the user clicked it. The
6
+ * order below is "the thing you type into first": xterm's hidden helper textarea, Monaco's
7
+ * edit context or textarea, then any other text surface, and only then the first focusable
8
+ * control.
9
+ *
10
+ * A panel slot can hold several tabs (the inactive ones are `display: none`), so hidden
11
+ * candidates are skipped — focusing one of those steals input from the visible tab.
12
+ */
13
+
14
+ /** The subset of an element this module touches; keeps the helper testable without a DOM. */
15
+ export interface FocusCandidate {
16
+ focus(): void;
17
+ checkVisibility?(): boolean;
18
+ readonly offsetParent?: unknown;
19
+ }
20
+
21
+ /** Text surfaces first, in the order a user would expect to type into them. */
22
+ export const PIP_FOCUS_SELECTORS = [
23
+ ".xterm-helper-textarea",
24
+ ".native-edit-context",
25
+ "textarea",
26
+ "[contenteditable]",
27
+ 'button, [href], input, select, [tabindex]:not([tabindex="-1"])',
28
+ ];
29
+
30
+ function isVisible(el: FocusCandidate): boolean {
31
+ // checkVisibility() is the accurate answer (display, content-visibility, hidden
32
+ // attribute) and exists wherever Document PiP does; offsetParent is the fallback
33
+ // for a test double or an older engine.
34
+ if (typeof el.checkVisibility === "function") return el.checkVisibility();
35
+ return el.offsetParent !== null && el.offsetParent !== undefined;
36
+ }
37
+
38
+ /**
39
+ * First visible match for the selector list, or null.
40
+ *
41
+ * Takes a query function rather than a root node so the caller keeps its own element type
42
+ * (`doc.querySelectorAll<HTMLElement>`) and a test can pass a plain fake.
43
+ */
44
+ export function pipFocusTarget<T extends FocusCandidate>(
45
+ query: (selector: string) => Iterable<T>,
46
+ ): T | null {
47
+ for (const selector of PIP_FOCUS_SELECTORS) {
48
+ for (const el of query(selector)) {
49
+ if (isVisible(el)) return el;
50
+ }
51
+ }
52
+ return null;
53
+ }
54
+
55
+ /** Focus the popped-out tab's primary input so the user can type straight away. */
56
+ export function focusPipDocument(doc: Document): void {
57
+ pipFocusTarget<HTMLElement>((selector) => doc.querySelectorAll<HTMLElement>(selector))?.focus();
58
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Size math for the PiP window request.
3
+ *
4
+ * Kept free of DOM reads (the screen bounds are an argument) so it is unit
5
+ * testable and so a caller can pass a floating window rect straight through.
6
+ */
7
+
8
+ export interface PipSize {
9
+ width: number;
10
+ height: number;
11
+ }
12
+
13
+ /** Below this a terminal/editor is unusable, and Chromium rejects tiny sizes. */
14
+ export const MIN_PIP_WIDTH = 320;
15
+ export const MIN_PIP_HEIGHT = 240;
16
+
17
+ /** Fallback bounds when no screen is available (SSR, tests). */
18
+ const FALLBACK_BOUNDS: PipSize = { width: 1920, height: 1080 };
19
+
20
+ function clampAxis(value: number, min: number, max: number): number {
21
+ // Non-finite input (NaN from an unmeasured rect) collapses to the minimum
22
+ // rather than propagating into the request.
23
+ if (!Number.isFinite(value)) return min;
24
+ return Math.round(Math.min(Math.max(value, min), Math.max(min, max)));
25
+ }
26
+
27
+ /** Read the usable screen area; safe to call without a window. */
28
+ export function screenBounds(): PipSize {
29
+ if (typeof window === "undefined" || !window.screen) return FALLBACK_BOUNDS;
30
+ const { availWidth, availHeight } = window.screen;
31
+ return {
32
+ width: Number.isFinite(availWidth) && availWidth > 0 ? availWidth : FALLBACK_BOUNDS.width,
33
+ height: Number.isFinite(availHeight) && availHeight > 0 ? availHeight : FALLBACK_BOUNDS.height,
34
+ };
35
+ }
36
+
37
+ /**
38
+ * Clamp a requested inner size to [min, screen] and round to whole CSS px.
39
+ * Chromium may still ignore the hint entirely — never assume the result.
40
+ */
41
+ export function clampPipSize(size: PipSize, bounds: PipSize = screenBounds()): PipSize {
42
+ return {
43
+ width: clampAxis(size.width, MIN_PIP_WIDTH, bounds.width),
44
+ height: clampAxis(size.height, MIN_PIP_HEIGHT, bounds.height),
45
+ };
46
+ }