@hienlh/ppm 0.18.10 → 0.18.11
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.
- package/.spike/cdp-client.ts +116 -0
- package/.spike/cleanup-ppm-workspace.mjs +44 -0
- package/.spike/pip-eval.ts +17 -0
- package/.spike/pip-page-helpers.js +119 -0
- package/.spike/pip-results-editor-glue.json +105 -0
- package/.spike/pip-results-editor.json +158 -0
- package/.spike/pip-results-input-isolation.json +28 -0
- package/.spike/pip-results-key-probe.json +58 -0
- package/.spike/pip-results-listener-survival.json +98 -0
- package/.spike/pip-results-listeners.json +36 -0
- package/.spike/pip-results-pagehide.json +92 -0
- package/.spike/pip-results-resize.json +104 -0
- package/.spike/pip-results-terminal-debug.json +99 -0
- package/.spike/pip-results-terminal-v2.json +191 -0
- package/.spike/pip-results-terminal.json +220 -0
- package/.spike/pip-results-xterm-trace.json +73 -0
- package/.spike/pip-spike-common.ts +83 -0
- package/.spike/pip-spike-editor-glue.ts +82 -0
- package/.spike/pip-spike-editor.ts +129 -0
- package/.spike/pip-spike-input-isolation.ts +38 -0
- package/.spike/pip-spike-key-probe.ts +34 -0
- package/.spike/pip-spike-listener-survival.ts +54 -0
- package/.spike/pip-spike-listeners.ts +19 -0
- package/.spike/pip-spike-pagehide.ts +59 -0
- package/.spike/pip-spike-resize.ts +42 -0
- package/.spike/pip-spike-setup.ts +63 -0
- package/.spike/pip-spike-terminal-debug.ts +81 -0
- package/.spike/pip-spike-terminal-v2.ts +139 -0
- package/.spike/pip-spike-terminal.ts +169 -0
- package/.spike/pip-spike-xterm-trace.ts +36 -0
- package/.spike/probe-drag-memo-error.mjs +67 -0
- package/.spike/read-dev-db.ts +15 -0
- package/.spike/scratch-editor-target.ts +7 -0
- package/.spike/smoke-unified-chrome-pip.mjs +353 -0
- package/.spike/tunnel.err +41 -0
- package/.spike/vite-restart.err +663 -0
- package/.spike/w.err +543 -0
- package/CHANGELOG.md +13 -0
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/http-api.md +1 -1
- package/dist/web/assets/adaptive-context-menu-DGCKKeTy.js +1 -0
- package/dist/web/assets/ai-resource-editor-BOHHTTe7.js +1 -0
- package/dist/web/assets/ai-settings-section-BigC_nZR.js +1 -0
- package/dist/web/assets/{angular-html-Ctz0zN01.js → angular-html-BYPaydvh.js} +1 -1
- package/dist/web/assets/{angular-ts-QXHpgB1C.js → angular-ts-Bb4AMKlk.js} +1 -1
- package/dist/web/assets/api-client-DTZEgjBQ.js +1 -0
- package/dist/web/assets/{api-settings-kQHV6pYZ.js → api-settings-Bd3M4YpI.js} +1 -1
- package/dist/web/assets/api-settings-kd1j4iR8.js +1 -0
- package/dist/web/assets/{api-themes-CrK0tkW_.js → api-themes-Cpx419SL.js} +1 -1
- package/dist/web/assets/{apl-b9KVk-O4.js → apl-DB2VjFCS.js} +1 -1
- package/dist/web/assets/architecture-PBZL5I3N-8dCMT9r7.js +1 -0
- package/dist/web/assets/{astro-BlFEeGYr.js → astro-BeoJdVpk.js} +1 -1
- package/dist/web/assets/{audio-preview-CZLmhf__.js → audio-preview-BgFuTn-0.js} +1 -1
- package/dist/web/assets/{blade-CGkj2MUI.js → blade-Cf2q1sPf.js} +1 -1
- package/dist/web/assets/{bsl-CVsbb6ap.js → bsl-W1kOaNpu.js} +1 -1
- package/dist/web/assets/{button-BA_fJOtX.js → button-5zTrkEoN.js} +1 -1
- package/dist/web/assets/{cairo-BbIHl2iE.js → cairo-BoAZFcje.js} +1 -1
- package/dist/web/assets/chat-tab-E3bf_V8X.js +15 -0
- package/dist/web/assets/chevron-down-Dp0rpHb8.js +1 -0
- package/dist/web/assets/clipboard-7fw0Shic.js +1 -0
- package/dist/web/assets/{cobol-BWSGjmWb.js → cobol-B0Nm7RXj.js} +1 -1
- package/dist/web/assets/code-editor-BUlM2gXk.js +10 -0
- package/dist/web/assets/{coffee-CWGNOxds.js → coffee-BakMn3on.js} +1 -1
- package/dist/web/assets/{conflict-editor-fRTU3f1o.js → conflict-editor-BUs5k9q_.js} +4 -4
- package/dist/web/assets/context-menu-Bq92km4s.js +1 -0
- package/dist/web/assets/{cpp-DHGV24J2.js → cpp-BRAJQHK2.js} +1 -1
- package/dist/web/assets/{crystal-Vlwf2UMP.js → crystal-kqqO3zkK.js} +1 -1
- package/dist/web/assets/{csv-preview-D1d0cxOJ.js → csv-preview-ByoDgLAZ.js} +1 -1
- package/dist/web/assets/{data-grid-overlay-editor-D9il5DZS.js → data-grid-overlay-editor-Brkf9z41.js} +1 -1
- package/dist/web/assets/database-viewer-Btc3h8Yu.js +1 -0
- package/dist/web/assets/dialog-DwtGlowE.js +1 -0
- package/dist/web/assets/diff-viewer-CZaDnR4w.js +4 -0
- package/dist/web/assets/docx-preview-DAD_vg59.js +12 -0
- package/dist/web/assets/{edge-Bhqk64zS.js → edge-Cq1ZKZuE.js} +1 -1
- package/dist/web/assets/{edit-diff-preview-gq6ALf2B.js → edit-diff-preview-B_VE7ppQ.js} +1 -1
- package/dist/web/assets/{elixir-D466WCFm.js → elixir-BM_JoJRk.js} +1 -1
- package/dist/web/assets/{elm-Bfs2qNPR.js → elm-Dw7oO08Y.js} +1 -1
- package/dist/web/assets/{erb-WI7jUaB6.js → erb-CfKOGAfk.js} +1 -1
- package/dist/web/assets/{erlang-BCBe8nCc.js → erlang-DlDmGVeE.js} +1 -1
- package/dist/web/assets/{esm-CZs9WVDO.js → esm-DGAP0GFh.js} +1 -1
- package/dist/web/assets/explorer-body-9aBmyVpZ.js +2 -0
- package/dist/web/assets/explorer-window-content-DRtqoSPA.js +1 -0
- package/dist/web/assets/extension-store-Cpfh2vMm.js +1 -0
- package/dist/web/assets/{extension-webview-BH_mWYMe.js → extension-webview-B2OnjuCu.js} +2 -2
- package/dist/web/assets/external-link-B8BynhvY.js +1 -0
- package/dist/web/assets/file-store-aOERIEo-.js +1 -0
- package/dist/web/assets/folder-symlink-B8XrtvQK.js +1 -0
- package/dist/web/assets/{fortran-fixed-form-CXLIv8Ox.js → fortran-fixed-form-XnAhQWxS.js} +1 -1
- package/dist/web/assets/{fsharp-CZsYmiw9.js → fsharp-CdNvy0PG.js} +1 -1
- package/dist/web/assets/{gdresource-BGRvoWfC.js → gdresource-DxuG5i8i.js} +1 -1
- package/dist/web/assets/{git-commit-DH6mY3Km.js → git-commit-3lMonsur.js} +1 -1
- package/dist/web/assets/git-log-panel-Co0PBPHC.js +1 -0
- package/dist/web/assets/{git-rebase-C5Gql6Ma.js → git-rebase-N8Z9kIMf.js} +1 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-2e_8dfbs.js +1 -0
- package/dist/web/assets/{glide-data-grid-n4ox_uev.js → glide-data-grid-C4_zIneN.js} +8 -8
- package/dist/web/assets/{glimmer-js-1-6JMJlj.js → glimmer-js-Dp9OXiib.js} +1 -1
- package/dist/web/assets/{glimmer-ts-C_Njj0nK.js → glimmer-ts-CDVKBcDj.js} +1 -1
- package/dist/web/assets/{glsl-DbkxE1TN.js → glsl-DPJxI4us.js} +1 -1
- package/dist/web/assets/{graphql-BK75fiXl.js → graphql-BrFhaQQl.js} +1 -1
- package/dist/web/assets/group-chat-tab-rOd8J8GC.js +1 -0
- package/dist/web/assets/{hack-DG151vit.js → hack-BzXbDMlA.js} +1 -1
- package/dist/web/assets/{haml-DKeIPQWM.js → haml-CPpkX0s5.js} +1 -1
- package/dist/web/assets/{handlebars-398uCI13.js → handlebars-BqrApy52.js} +1 -1
- package/dist/web/assets/{html-NLWdst5q.js → html-DmjUl-OA.js} +1 -1
- package/dist/web/assets/{html-derivative-CJf_Le2z.js → html-derivative-Cnd6XFR5.js} +1 -1
- package/dist/web/assets/{http-G1K2FozA.js → http-DMLWYun2.js} +1 -1
- package/dist/web/assets/{hurl-WDC6sSBz.js → hurl-CKkCVxbj.js} +1 -1
- package/dist/web/assets/{hxml-Dc3jBXuf.js → hxml-CAx19TtQ.js} +1 -1
- package/dist/web/assets/image-preview-DHUoylQ1.js +1 -0
- package/dist/web/assets/index-BImUaigO.js +52 -0
- package/dist/web/assets/index-CSfi6DSU.css +2 -0
- package/dist/web/assets/info-3K5VOQVL-BZi1Gha1.js +1 -0
- package/dist/web/assets/input-DcEk7mA3.js +1 -0
- package/dist/web/assets/{jinja-CWsQj2y0.js → jinja-BmB9YN9l.js} +1 -1
- package/dist/web/assets/{jison-CciJg2NW.js → jison-BaVsKKpw.js} +1 -1
- package/dist/web/assets/{julia-IOQNJAB7.js → julia-BgVBLveX.js} +1 -1
- package/dist/web/assets/{just-BGdHchwS.js → just-C2ENIbl9.js} +1 -1
- package/dist/web/assets/keybindings-store-BGIyqXHI.js +1 -0
- package/dist/web/assets/keybindings-store-CzV2sPls.js +1 -0
- package/dist/web/assets/{latex-D6TOl-L2.js → latex-BiDIWxKL.js} +1 -1
- package/dist/web/assets/{liquid-CVSvu_Wn.js → liquid-NxpapreE.js} +1 -1
- package/dist/web/assets/loader-circle-gSPVxfvH.js +1 -0
- package/dist/web/assets/lock-Did-87UV.js +1 -0
- package/dist/web/assets/{lua-CcKiU6HW.js → lua-DVepQvwH.js} +1 -1
- package/dist/web/assets/markdown-renderer-CcbR33VG.js +1 -0
- package/dist/web/assets/{markdown-renderer-B317vEys.js → markdown-renderer-DlcDhgrF.js} +3 -3
- package/dist/web/assets/{marko--UOicMGo.js → marko-CJ2606Xl.js} +1 -1
- package/dist/web/assets/{mdc-D690aU2C.js → mdc-D2bjqclE.js} +1 -1
- package/dist/web/assets/{media-url-CylYQld1.js → media-url-H17XJF-I.js} +1 -1
- package/dist/web/assets/mobile-bottom-sheet-g-r2hCFa.js +1 -0
- package/dist/web/assets/mobile-explorer-sheet-SIwQXlwA.js +1 -0
- package/dist/web/assets/monitor-Dv8vn_6O.js +1 -0
- package/dist/web/assets/{nextflow-DR8PhpF8.js → nextflow-BtJwUbfF.js} +1 -1
- package/dist/web/assets/{nginx-Qb9pUk1g.js → nginx-j4gyIhHE.js} +1 -1
- package/dist/web/assets/{nim-DLa8R3NS.js → nim-ClH_gjP5.js} +1 -1
- package/dist/web/assets/notification-store-DV5QtUTg.js +1 -0
- package/dist/web/assets/{number-overlay-editor-D9SkFg1Y.js → number-overlay-editor-C1EqJnWq.js} +1 -1
- package/dist/web/assets/{overview-panel-BxDohIEa.js → overview-panel-vTeeJYVZ.js} +1 -1
- package/dist/web/assets/packet-RMMSAZCW-o5htEcin.js +1 -0
- package/dist/web/assets/panel-store-BSnkjgHt.js +1 -0
- package/dist/web/assets/pdf-preview-CqFGRY0Z.js +1 -0
- package/dist/web/assets/pencil-BlIIg6RH.js +1 -0
- package/dist/web/assets/{perl-AMNGIneF.js → perl-C9H7X7CT.js} +1 -1
- package/dist/web/assets/{php-CDsOOxXn.js → php-Bx2U-cQ_.js} +1 -1
- package/dist/web/assets/pie-UPGHQEXC-BXAIFSAD.js +1 -0
- package/dist/web/assets/play-4MZi1Axp.js +1 -0
- package/dist/web/assets/portal-container-context-Cm5HipFr.js +1 -0
- package/dist/web/assets/{postgres-viewer-BWZLW7kI.js → postgres-viewer-DHwcQucn.js} +3 -3
- package/dist/web/assets/process-table-BGRJNlpn.js +1 -0
- package/dist/web/assets/{project-store-B8BkHXy5.js → project-store--nvQiy75.js} +1 -1
- package/dist/web/assets/{pug-C2kdkhQ6.js → pug-Cw74sKsE.js} +1 -1
- package/dist/web/assets/{qml-DRDkUp75.js → qml-BXD94Eqz.js} +1 -1
- package/dist/web/assets/radar-KQ55EAFF-Dbt2Aebl.js +1 -0
- package/dist/web/assets/{razor-wY_6wUeC.js → razor-DZ0-Ge0S.js} +1 -1
- package/dist/web/assets/refresh-cw-B06yaBrW.js +1 -0
- package/dist/web/assets/rotate-ccw-COXu_9oj.js +1 -0
- package/dist/web/assets/{rst-BRpofyNs.js → rst-Dtdh0QUj.js} +1 -1
- package/dist/web/assets/{ruby-ieATBhWm.js → ruby-BC51BW2Q.js} +1 -1
- package/dist/web/assets/{run-in-terminal-CyS5Itj-.js → run-in-terminal-Sd3KyjN4.js} +1 -1
- package/dist/web/assets/{sas-CoOOEbOO.js → sas-BN8i4qOU.js} +1 -1
- package/dist/web/assets/scroll-area-0gljZ6lF.js +1 -0
- package/dist/web/assets/{scss-_nWV0bsb.js → scss-H-QtA7Rz.js} +1 -1
- package/dist/web/assets/send-BlyNJAzy.js +1 -0
- package/dist/web/assets/{send-to-chat-BcO39BDR.js → send-to-chat-u6m8l-rH.js} +1 -1
- package/dist/web/assets/{settings-store-C20lqh0G.js → settings-store-CHY6Kzin.js} +2 -2
- package/dist/web/assets/settings-tab-Dic6TKkU.js +1 -0
- package/dist/web/assets/settings-tab-IY6K1MiZ.js +3 -0
- package/dist/web/assets/{shaderlab-XkqfIfO8.js → shaderlab-CalNsj_x.js} +1 -1
- package/dist/web/assets/shallow-DYo6goJ4.js +1 -0
- package/dist/web/assets/{shellsession-BKBIqTlM.js → shellsession-BFrcoR8x.js} +1 -1
- package/dist/web/assets/{soy-oVDnPzzh.js → soy-CNbku7vP.js} +1 -1
- package/dist/web/assets/{sparql-N2VclEsF.js → sparql-BN_orcVp.js} +1 -1
- package/dist/web/assets/{sql-query-editor-BwPjEaP9.js → sql-query-editor-C6pC3I8l.js} +1 -1
- package/dist/web/assets/sqlite-viewer-DTr5PzUb.js +1 -0
- package/dist/web/assets/{stata-BuuClVDg.js → stata-C6a5Ijzq.js} +1 -1
- package/dist/web/assets/{surrealql-DE5_63MS.js → surrealql-ClplI_HY.js} +1 -1
- package/dist/web/assets/{svelte--YWjlOrK.js → svelte-DNm-UNXB.js} +1 -1
- package/dist/web/assets/switch-DKvKya9y.js +1 -0
- package/dist/web/assets/system-monitor-body-iwGiCns9.js +2 -0
- package/dist/web/assets/system-monitor-tab-DdXQhEel.js +1 -0
- package/dist/web/assets/system-monitor-window-content-BUqRsPK2.js +1 -0
- package/dist/web/assets/tab-host-window-content-BnqGPu8a.js +1 -0
- package/dist/web/assets/{tab-store-DAsvpx4t.js → tab-store-CJuJRapl.js} +1 -1
- package/dist/web/assets/team-member-sheet-LkAFSCvb.js +2 -0
- package/dist/web/assets/team-member-window-content-T4Q5JI-G.js +1 -0
- package/dist/web/assets/{templ-MlpvJx4a.js → templ-CSdqVobu.js} +1 -1
- package/dist/web/assets/terminal-tab-Bb2rZegQ.js +3 -0
- package/dist/web/assets/{tex-0loAoXJG.js → tex-DzSJ4kcZ.js} +1 -1
- package/dist/web/assets/text-wrap-CBT4Gxtg.js +1 -0
- package/dist/web/assets/tool-cards-lhqhrDTT.js +8 -0
- package/dist/web/assets/trash-2-Bk4yYlck.js +1 -0
- package/dist/web/assets/treemap-KZPCXAKY-DUbnl9dz.js +1 -0
- package/dist/web/assets/triangle-alert-B8EYecpe.js +1 -0
- package/dist/web/assets/{ts-tags-pt-Ug0hK.js → ts-tags-C28w3bTg.js} +1 -1
- package/dist/web/assets/{twig-DOePpLOL.js → twig-i5jY3QXB.js} +1 -1
- package/dist/web/assets/upload-BNlX8D07.js +1 -0
- package/dist/web/assets/{use-blob-url-BKyVxOZw.js → use-blob-url-Dsq9OjTh.js} +1 -1
- package/dist/web/assets/{use-monaco-theme-DSCdlrjO.js → use-monaco-theme-BZvlsoBv.js} +1 -1
- package/dist/web/assets/use-open-team-member-DkiEjFYE.js +1 -0
- package/dist/web/assets/{use-websocket-iJfc7EbK.js → use-websocket-B8R50f7f.js} +1 -1
- package/dist/web/assets/{vendor-mermaid-DrwG0NYt.js → vendor-mermaid-By4AVvJY.js} +1 -1
- package/dist/web/assets/video-preview-m0-3p7QZ.js +1 -0
- package/dist/web/assets/{vue-D6f-rprj.js → vue-Ceyet_lv.js} +1 -1
- package/dist/web/assets/{vue-html-DEYRkS1V.js → vue-html-GuU7g_hg.js} +1 -1
- package/dist/web/assets/{vue-vine-CxSG2ojf.js → vue-vine-CxXoaJr2.js} +1 -1
- package/dist/web/assets/window-store-CsEW6jiE.js +1 -0
- package/dist/web/assets/{xml-DhrxbATj.js → xml-CbqOVhkP.js} +1 -1
- package/dist/web/assets/{xsl-CU0ZndUO.js → xsl-KfAmCauy.js} +1 -1
- package/dist/web/index.html +56 -27
- package/dist/web/sw.js +1 -1
- package/docs/code-standards.md +8 -0
- package/docs/codebase-summary.md +19 -5
- package/docs/design-guidelines.md +13 -2
- package/docs/project-roadmap.md +9 -0
- package/docs/system-architecture.md +83 -6
- package/package.json +1 -1
- package/src/web/components/chat/file-picker.tsx +5 -2
- package/src/web/components/chat/mode-selector.tsx +5 -2
- package/src/web/components/chat/model-selector.tsx +5 -2
- package/src/web/components/chat/model-thinking-selector.tsx +5 -2
- package/src/web/components/chat/provider-selector.tsx +5 -2
- package/src/web/components/chat/slash-command-picker.tsx +5 -2
- package/src/web/components/editor/code-editor.tsx +13 -3
- package/src/web/components/editor/conflict-editor.tsx +9 -0
- package/src/web/components/editor/diff-viewer.tsx +9 -0
- package/src/web/components/floating-window/floating-window.tsx +23 -15
- package/src/web/components/floating-window/pip/pip-caption-button.tsx +108 -0
- package/src/web/components/floating-window/pip/pip-focus-target.ts +58 -0
- package/src/web/components/floating-window/pip/pip-geometry.ts +46 -0
- package/src/web/components/floating-window/pip/pip-host.ts +156 -0
- package/src/web/components/floating-window/pip/pip-key-forward.ts +59 -0
- package/src/web/components/floating-window/pip/pip-resize-signal.ts +33 -0
- package/src/web/components/floating-window/pip/pip-style-copy.ts +108 -0
- package/src/web/components/floating-window/pip/pip-support.ts +33 -0
- package/src/web/components/floating-window/tab-host-window-content.tsx +80 -0
- package/src/web/components/floating-window/use-window-body-element.ts +67 -0
- package/src/web/components/floating-window/use-window-drag.ts +5 -0
- package/src/web/components/floating-window/use-window-gesture-context.ts +14 -0
- package/src/web/components/floating-window/use-window-resize.ts +5 -0
- package/src/web/components/floating-window/window-content-registry.ts +4 -16
- package/src/web/components/floating-window/window-layer.tsx +1 -2
- package/src/web/components/floating-window/window-persistence.ts +9 -2
- package/src/web/components/floating-window/window-pip-placeholder.tsx +31 -0
- package/src/web/components/floating-window/window-pip-registry.ts +69 -0
- package/src/web/components/floating-window/window-skin-chrome.tsx +21 -0
- package/src/web/components/floating-window/window-store-types.ts +8 -2
- package/src/web/components/layout/reparenting-tab.tsx +136 -0
- package/src/web/components/layout/tab-bar.tsx +2 -0
- package/src/web/components/layout/tab-pool-collect.ts +38 -2
- package/src/web/components/layout/tab-pool-registry.ts +48 -0
- package/src/web/components/layout/tab-pool.tsx +54 -168
- package/src/web/components/layout/tab-pop-out-menu-item.tsx +42 -0
- package/src/web/components/layout/use-window-panel-reconcile.ts +48 -0
- package/src/web/components/os-explorer/skins/macos-window-chrome.tsx +16 -7
- package/src/web/components/os-explorer/skins/windows-window-chrome.tsx +14 -8
- package/src/web/components/ui/context-menu.tsx +10 -3
- package/src/web/components/ui/dialog.tsx +10 -1
- package/src/web/components/ui/dropdown-menu.tsx +10 -3
- package/src/web/components/ui/mobile-bottom-sheet.tsx +7 -4
- package/src/web/components/ui/portal-container-context.tsx +40 -0
- package/src/web/components/ui/select.tsx +3 -1
- package/src/web/components/ui/tooltip.tsx +3 -1
- package/src/web/hooks/use-terminal.ts +24 -3
- package/src/web/stores/panel-store.ts +72 -7
- package/src/web/stores/panel-utils.ts +36 -0
- package/src/web/stores/window-panel-actions.ts +211 -0
- package/src/web/stores/window-panel-persistence.ts +115 -0
- package/src/web/stores/window-panel-reconcile.ts +97 -0
- package/dist/web/assets/ai-resource-editor-mdDKG-rw.js +0 -1
- package/dist/web/assets/api-client-CzABTreM.js +0 -1
- package/dist/web/assets/api-settings-nblja3Rk.js +0 -1
- package/dist/web/assets/architecture-PBZL5I3N-C7ra20CE.js +0 -1
- package/dist/web/assets/chat-tab-C060A94y.js +0 -15
- package/dist/web/assets/code-editor-WELegzdp.js +0 -10
- package/dist/web/assets/context-menu-Cq0u3SK9.js +0 -1
- package/dist/web/assets/database-viewer-DevnWTV4.js +0 -1
- package/dist/web/assets/diff-viewer-DGxVg1pD.js +0 -4
- package/dist/web/assets/docx-preview-Cx-zLwAw.js +0 -12
- package/dist/web/assets/explorer-body-j_4hVc34.js +0 -2
- package/dist/web/assets/explorer-window-content-DdrGwk3w.js +0 -1
- package/dist/web/assets/git-log-panel-CfpXRJcP.js +0 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-D4hYLNJU.js +0 -1
- package/dist/web/assets/group-chat-tab-dYuuknLN.js +0 -1
- package/dist/web/assets/image-preview-Ss38ex8g.js +0 -1
- package/dist/web/assets/index-BiTiXgBZ.css +0 -2
- package/dist/web/assets/index-Ch8l9de-.js +0 -52
- package/dist/web/assets/info-3K5VOQVL-lRlrTlkb.js +0 -1
- package/dist/web/assets/keybindings-store-CDfTjwZX.js +0 -1
- package/dist/web/assets/markdown-renderer-CpRlpLHw.js +0 -1
- package/dist/web/assets/mobile-bottom-sheet-BUOJgiaZ.js +0 -1
- package/dist/web/assets/mobile-explorer-sheet-D1Bv9UCT.js +0 -1
- package/dist/web/assets/notification-store-KwTAZT8b.js +0 -1
- package/dist/web/assets/packet-RMMSAZCW-BIhk1mvp.js +0 -1
- package/dist/web/assets/panel-store-DCD82zc1.js +0 -1
- package/dist/web/assets/pdf-preview-dwRe54ht.js +0 -1
- package/dist/web/assets/pie-UPGHQEXC-SLS6i76l.js +0 -1
- package/dist/web/assets/process-table-CI-fnVsy.js +0 -1
- package/dist/web/assets/radar-KQ55EAFF-JJ6O1Er_.js +0 -1
- package/dist/web/assets/settings-tab-mPxrKkfm.js +0 -1
- package/dist/web/assets/sqlite-viewer-Cs-_D942.js +0 -1
- package/dist/web/assets/system-monitor-body-CV7-0hZG.js +0 -2
- package/dist/web/assets/system-monitor-tab-Ce-8Axhh.js +0 -1
- package/dist/web/assets/system-monitor-window-content-CetwYOQy.js +0 -1
- package/dist/web/assets/team-member-sheet-CjgaQjsZ.js +0 -2
- package/dist/web/assets/team-member-window-content-DNJiYWS7.js +0 -1
- package/dist/web/assets/terminal-tab-DF7521sT.js +0 -3
- package/dist/web/assets/tool-cards-DCAXGDJI.js +0 -8
- package/dist/web/assets/treemap-KZPCXAKY-Be3KNmns.js +0 -1
- package/dist/web/assets/use-open-team-member-H4k74HnV.js +0 -1
- package/dist/web/assets/video-preview-B0ZWpX0F.js +0 -1
- package/src/web/components/floating-window/default-window-chrome.tsx +0 -71
- package/src/web/components/os-explorer/skins/explorer-skin-chrome.tsx +0 -17
- /package/dist/web/assets/{abap-MRbmsXOs.js → abap-C6nB04tn.js} +0 -0
- /package/dist/web/assets/{actionscript-3-BDDHKqa4.js → actionscript-3-Vx4rw2sC.js} +0 -0
- /package/dist/web/assets/{ada-DpuV9KwV.js → ada-Ccd8vM20.js} +0 -0
- /package/dist/web/assets/{andromeeda-D6qUCKJo.js → andromeeda-DnBX5xMg.js} +0 -0
- /package/dist/web/assets/{apache-CX1NU_Tl.js → apache-B-9_sx0g.js} +0 -0
- /package/dist/web/assets/{apex-B4-aoQ3K.js → apex-_wPVBYoL.js} +0 -0
- /package/dist/web/assets/{api-client-BSB14J4w.js → api-client-aQb5hHE5.js} +0 -0
- /package/dist/web/assets/{applescript-Dm9NI6KR.js → applescript-CcvD-qr0.js} +0 -0
- /package/dist/web/assets/{apply-theme-BH_d4amk.js → apply-theme-BeLRfsSu.js} +0 -0
- /package/dist/web/assets/{ara-BGN8GAYn.js → ara-C40Ztoms.js} +0 -0
- /package/dist/web/assets/{asciidoc-s_yVuR3t.js → asciidoc-CybYkJV4.js} +0 -0
- /package/dist/web/assets/{asm-BzQdSvTe.js → asm-9eOKwzR0.js} +0 -0
- /package/dist/web/assets/{aurora-x-BJTLETG_.js → aurora-x-B5ZH4t7t.js} +0 -0
- /package/dist/web/assets/{awk-BQEGWxvX.js → awk-Dqilob-2.js} +0 -0
- /package/dist/web/assets/{ayu-dark-CpTORmLc.js → ayu-dark-CPgRhf5r.js} +0 -0
- /package/dist/web/assets/{ayu-light-D8PVj-e6.js → ayu-light-Do06Q52f.js} +0 -0
- /package/dist/web/assets/{ayu-mirage-DyElQHtm.js → ayu-mirage-_BhxcrxY.js} +0 -0
- /package/dist/web/assets/{ballerina-C82NkRtj.js → ballerina-DDwK54QW.js} +0 -0
- /package/dist/web/assets/{bat-0X7DtGI-.js → bat-BGyGlzGk.js} +0 -0
- /package/dist/web/assets/{beancount-Xgvy6YRl.js → beancount-CRWBdapI.js} +0 -0
- /package/dist/web/assets/{berry-CCT2pZcQ.js → berry-DbSFn2gO.js} +0 -0
- /package/dist/web/assets/{bibtex-CpXgZ9M_.js → bibtex-QpsV9gm9.js} +0 -0
- /package/dist/web/assets/{bicep-fkeSA62l.js → bicep-CxS8CUve.js} +0 -0
- /package/dist/web/assets/{bird2-Co7SeAI8.js → bird2-CuZhQzYR.js} +0 -0
- /package/dist/web/assets/{bot-CunPuEdW.js → bot-D6sx11y0.js} +0 -0
- /package/dist/web/assets/{c-BpmrTvJh.js → c-9bnDqE3g.js} +0 -0
- /package/dist/web/assets/{c3-BZ_Z0RrR.js → c3-JMZTrOhA.js} +0 -0
- /package/dist/web/assets/{cadence-B0GBC8OF.js → cadence-DsDNayJS.js} +0 -0
- /package/dist/web/assets/{can-open-in-ppm-omBzUBBq.js → can-open-in-ppm-BJfpynya.js} +0 -0
- /package/dist/web/assets/{catppuccin-frappe-DIt_xR7m.js → catppuccin-frappe-DYIKXXBe.js} +0 -0
- /package/dist/web/assets/{catppuccin-latte-Dw40AcqA.js → catppuccin-latte-IYYOnUJ8.js} +0 -0
- /package/dist/web/assets/{catppuccin-macchiato-BJ7DfVEF.js → catppuccin-macchiato-BrJ_7mfS.js} +0 -0
- /package/dist/web/assets/{catppuccin-mocha-NI2lfXzU.js → catppuccin-mocha-gzSu7v7-.js} +0 -0
- /package/dist/web/assets/{chevron-right-BLOtX8Vy.js → chevron-right-De-Wz5Lz.js} +0 -0
- /package/dist/web/assets/{circle-hjUGru6R.js → circle-BCy0AUCo.js} +0 -0
- /package/dist/web/assets/{clarity-F39L0xMJ.js → clarity-DLzsC0Hb.js} +0 -0
- /package/dist/web/assets/{clock-CvhF4DJP.js → clock-C1CQUQPZ.js} +0 -0
- /package/dist/web/assets/{clojure-DloMkd8K.js → clojure-DS1BvoTt.js} +0 -0
- /package/dist/web/assets/{cmake-CwerJun_.js → cmake-CDvsJwYp.js} +0 -0
- /package/dist/web/assets/{code-DDPoqVri.js → code-DJgYrFzm.js} +0 -0
- /package/dist/web/assets/{codeowners-CQyVz4Qf.js → codeowners-BjsYiflJ.js} +0 -0
- /package/dist/web/assets/{codeql-Bb229zuY.js → codeql-CG-7ARat.js} +0 -0
- /package/dist/web/assets/{common-lisp-KMlIwq5I.js → common-lisp-DSO1Lbh9.js} +0 -0
- /package/dist/web/assets/{copy-DKn11Pye.js → copy-BewHj66E.js} +0 -0
- /package/dist/web/assets/{coq-DHX_3IIo.js → coq-DYdh3oP_.js} +0 -0
- /package/dist/web/assets/{csharp-CEmCZv9Q.js → csharp-DxEBz5s0.js} +0 -0
- /package/dist/web/assets/{css-CqZqBD05.js → css-dal3Q-8C.js} +0 -0
- /package/dist/web/assets/{csv-l1g_V5MV.js → csv-CpqjMGiA.js} +0 -0
- /package/dist/web/assets/{csv-parser-CnS0wqr6.js → csv-parser-3umBA4NY.js} +0 -0
- /package/dist/web/assets/{cue-BrxRmilg.js → cue-DinoJ_5k.js} +0 -0
- /package/dist/web/assets/{cypher-rZkKwqZc.js → cypher-DzxqmkUW.js} +0 -0
- /package/dist/web/assets/{d-BALR-QuP.js → d-BxNwJuEC.js} +0 -0
- /package/dist/web/assets/{dark-plus-Cj7rVwh-.js → dark-plus-Clmv3V-0.js} +0 -0
- /package/dist/web/assets/{dart-CWQcdkXk.js → dart-BWVtXD35.js} +0 -0
- /package/dist/web/assets/{data-grid-types-CYvF-xK5.js → data-grid-types-B4n51Fck.js} +0 -0
- /package/dist/web/assets/{database-BH0urvbs.js → database-Y3ESDK4-.js} +0 -0
- /package/dist/web/assets/{dax-BNHD-QBA.js → dax-DsImuWgJ.js} +0 -0
- /package/dist/web/assets/{desktop-CN0IXPrP.js → desktop-B0jJuG2r.js} +0 -0
- /package/dist/web/assets/{diff-BtOXapES.js → diff-CWqAAxoE.js} +0 -0
- /package/dist/web/assets/{dist-DB1Oaqcc.js → dist-B-EXdSYE.js} +0 -0
- /package/dist/web/assets/{dist-Di6G_5jU.js → dist-C0eNNfbt.js} +0 -0
- /package/dist/web/assets/{docker-DNsAo_qO.js → docker-CYFCJdIL.js} +0 -0
- /package/dist/web/assets/{dotenv-D6Pl6aOU.js → dotenv-CKDUjURg.js} +0 -0
- /package/dist/web/assets/{download-zCATy4x4.js → download-DG3_9xXy.js} +0 -0
- /package/dist/web/assets/{dracula-C3m-w12D.js → dracula-CSoPspHE.js} +0 -0
- /package/dist/web/assets/{dracula-soft-BYqvXm6Z.js → dracula-soft-BuFjw5L1.js} +0 -0
- /package/dist/web/assets/{dream-maker-DZAPbPTi.js → dream-maker-B6PdDRZu.js} +0 -0
- /package/dist/web/assets/{emacs-lisp-Ao5SW8ay.js → emacs-lisp-CMcXvD0G.js} +0 -0
- /package/dist/web/assets/{everforest-dark-uC8QYotQ.js → everforest-dark-cU8-wYzi.js} +0 -0
- /package/dist/web/assets/{everforest-light-CTgsVNMr.js → everforest-light-KhorllqK.js} +0 -0
- /package/dist/web/assets/{fennel-WuBw6IR1.js → fennel-BCELZK87.js} +0 -0
- /package/dist/web/assets/{file-exclamation-point-COAwgNGw.js → file-exclamation-point-CZ4DiR75.js} +0 -0
- /package/dist/web/assets/{fish-Byy9dusu.js → fish-BQc0y_jy.js} +0 -0
- /package/dist/web/assets/{fluent-CDxb_sgw.js → fluent-BTINnwF6.js} +0 -0
- /package/dist/web/assets/{format-bytes-BE_W3UBg.js → format-bytes-WVcFxJuT.js} +0 -0
- /package/dist/web/assets/{fortran-free-form-DKWSTamT.js → fortran-free-form-BQim9wDz.js} +0 -0
- /package/dist/web/assets/{gdscript-prYHMgtD.js → gdscript-03w5u8un.js} +0 -0
- /package/dist/web/assets/{gdshader-D-RM-SQk.js → gdshader-Dp2daNzU.js} +0 -0
- /package/dist/web/assets/{genie-CowkJhej.js → genie-CoNcjPiD.js} +0 -0
- /package/dist/web/assets/{gherkin-CLFpoVYJ.js → gherkin-NrPOSPQL.js} +0 -0
- /package/dist/web/assets/{github-dark-default-BK_1Qgb8.js → github-dark-default-DOKw-1cI.js} +0 -0
- /package/dist/web/assets/{github-dark-dimmed-Cv9lj6f-.js → github-dark-dimmed-DJRNMkEA.js} +0 -0
- /package/dist/web/assets/{github-dark-high-contrast-CW5ZgIDh.js → github-dark-high-contrast-Bj7jJ_Gs.js} +0 -0
- /package/dist/web/assets/{github-dark-nW2F-RLd.js → github-dark-z4RE9ZqA.js} +0 -0
- /package/dist/web/assets/{github-light-D4PqBHGZ.js → github-light-B4k_yMFu.js} +0 -0
- /package/dist/web/assets/{github-light-default-B-cHtJJV.js → github-light-default-BHc-Uzhs.js} +0 -0
- /package/dist/web/assets/{github-light-high-contrast-Dt0HJq50.js → github-light-high-contrast-CHisIywL.js} +0 -0
- /package/dist/web/assets/{gleam-DwSyXJWP.js → gleam-CfbypZ4q.js} +0 -0
- /package/dist/web/assets/{gn-Cv5WEzHc.js → gn-YoAjyhJa.js} +0 -0
- /package/dist/web/assets/{gnuplot-D7bRdY_M.js → gnuplot-xVkc1f1c.js} +0 -0
- /package/dist/web/assets/{go-DiRVJ22U.js → go-GPCwP3Gu.js} +0 -0
- /package/dist/web/assets/{groovy-BHAgLTeO.js → groovy-Crh4Yww9.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-hard-C8QZ3gzY.js → gruvbox-dark-hard-BluUFuDS.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-medium-Dp1eeid2.js → gruvbox-dark-medium-Cxk1FWQp.js} +0 -0
- /package/dist/web/assets/{gruvbox-dark-soft-Cwq0dWVj.js → gruvbox-dark-soft-CHXMiFmj.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-hard-CLQCq2-w.js → gruvbox-light-hard-B6eKPjAD.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-medium-APHsh6Mo.js → gruvbox-light-medium-pDwMm1ut.js} +0 -0
- /package/dist/web/assets/{gruvbox-light-soft-CX-fYc64.js → gruvbox-light-soft-Cxu6kHqK.js} +0 -0
- /package/dist/web/assets/{haskell-C4Tw-TDa.js → haskell-C6JKHjbK.js} +0 -0
- /package/dist/web/assets/{haxe-B7fSduTQ.js → haxe-BuBNdF0a.js} +0 -0
- /package/dist/web/assets/{hcl-Bi3ho6yC.js → hcl-DZpDdGj2.js} +0 -0
- /package/dist/web/assets/{hjson-BXwae2M1.js → hjson-CBkhYRuo.js} +0 -0
- /package/dist/web/assets/{hlsl-CRuQLBSa.js → hlsl-C5nMxnp9.js} +0 -0
- /package/dist/web/assets/{horizon-DtdQ6qjv.js → horizon-VAFvA6R6.js} +0 -0
- /package/dist/web/assets/{horizon-bright-BXSF_uKq.js → horizon-bright-BC0xn7T3.js} +0 -0
- /package/dist/web/assets/{houston-C6ASpUjT.js → houston-BxrUivmz.js} +0 -0
- /package/dist/web/assets/{hy-BrWBHtHY.js → hy-DLtOXoaH.js} +0 -0
- /package/dist/web/assets/{image-gallery-CGvlv8zR.js → image-gallery-Gnf7TdCR.js} +0 -0
- /package/dist/web/assets/{imba-C_JJXckG.js → imba-BdpFXM2W.js} +0 -0
- /package/dist/web/assets/{ini-DEE_vSHQ.js → ini-BInJO_T0.js} +0 -0
- /package/dist/web/assets/{java-CnmpcjcT.js → java-Dxuddnkb.js} +0 -0
- /package/dist/web/assets/{javascript-C-M7sa2e.js → javascript-CVamJfLY.js} +0 -0
- /package/dist/web/assets/{json-BjZ3dAk6.js → json-BLZ0ozYk.js} +0 -0
- /package/dist/web/assets/{json5-BQ2vpqjp.js → json5-BnXzmMKs.js} +0 -0
- /package/dist/web/assets/{jsonc-C5MjoWGx.js → jsonc-CSgkSga7.js} +0 -0
- /package/dist/web/assets/{jsonl-JvhrmQJI.js → jsonl-CY5W2nF2.js} +0 -0
- /package/dist/web/assets/{jsonnet-C5pdZVuo.js → jsonnet-CEJYH3sF.js} +0 -0
- /package/dist/web/assets/{jssm-Db17uybX.js → jssm-CsJc7Uhk.js} +0 -0
- /package/dist/web/assets/{jsx-tJp2Cyqu.js → jsx-jCiRaHU7.js} +0 -0
- /package/dist/web/assets/{kanagawa-dragon-BculT_Y1.js → kanagawa-dragon-DfoA_GxX.js} +0 -0
- /package/dist/web/assets/{kanagawa-lotus-yQgHUGwU.js → kanagawa-lotus-BOLYJpWd.js} +0 -0
- /package/dist/web/assets/{kanagawa-wave-CyGoWN4d.js → kanagawa-wave-DfKlbT1G.js} +0 -0
- /package/dist/web/assets/{kdl-Bn8R1REF.js → kdl-CmssIFTi.js} +0 -0
- /package/dist/web/assets/{kotlin-DWughK73.js → kotlin-BRsNgp6x.js} +0 -0
- /package/dist/web/assets/{kusto--serPb0x.js → kusto-T8X9jUab.js} +0 -0
- /package/dist/web/assets/{laserwave-DfAPJ1tt.js → laserwave-DkJMVJ8Z.js} +0 -0
- /package/dist/web/assets/{lean-UAm1HOKl.js → lean-C65KGVPq.js} +0 -0
- /package/dist/web/assets/{less-Xj6Ka0fF.js → less-exIPdDlf.js} +0 -0
- /package/dist/web/assets/{lib-DgNcCtj3.js → lib-mC1NZfuw.js} +0 -0
- /package/dist/web/assets/{libesm-CPh1Av0r.js → libesm-DSutUtl1.js} +0 -0
- /package/dist/web/assets/{light-plus-BfS7gPcj.js → light-plus-DiHUXAZt.js} +0 -0
- /package/dist/web/assets/{llvm-DvWiVwvU.js → llvm-CJBnEzFM.js} +0 -0
- /package/dist/web/assets/{log-Bo5z9bNz.js → log-DxMyUMuP.js} +0 -0
- /package/dist/web/assets/{logo-CrIjcMZT.js → logo-CC9NKzca.js} +0 -0
- /package/dist/web/assets/{luau-C9TsYwNt.js → luau-Bw10I6zf.js} +0 -0
- /package/dist/web/assets/{make-GYq4qVbx.js → make-C_6M90m6.js} +0 -0
- /package/dist/web/assets/{markdown-p5mNledS.js → markdown-bR9_R-LF.js} +0 -0
- /package/dist/web/assets/{material-theme-CWYOVxsP.js → material-theme-BUx2Qujn.js} +0 -0
- /package/dist/web/assets/{material-theme-darker-BDGty7YH.js → material-theme-darker-CRJrPgKm.js} +0 -0
- /package/dist/web/assets/{material-theme-lighter-JbgOgV3n.js → material-theme-lighter-CUAYppPa.js} +0 -0
- /package/dist/web/assets/{material-theme-ocean-EMOpLpa2.js → material-theme-ocean-DuINF1fg.js} +0 -0
- /package/dist/web/assets/{material-theme-palenight-CY5hgm7h.js → material-theme-palenight-W6_icGCj.js} +0 -0
- /package/dist/web/assets/{matlab-C-He_NTH.js → matlab-rfqn_b3z.js} +0 -0
- /package/dist/web/assets/{mdx-Cr2TR5fj.js → mdx-Bh1B_YOJ.js} +0 -0
- /package/dist/web/assets/{mermaid-BYc0-B0U.js → mermaid-Dxf6Ya2k.js} +0 -0
- /package/dist/web/assets/{min-dark-CMJwqJqB.js → min-dark-CivZ2L0h.js} +0 -0
- /package/dist/web/assets/{min-light-Cx6vFiEX.js → min-light-B1Ykqtma.js} +0 -0
- /package/dist/web/assets/{mipsasm-Bjer5HwK.js → mipsasm-DynHaM0d.js} +0 -0
- /package/dist/web/assets/{mojo-t90PR-Y2.js → mojo-Clw5PbGH.js} +0 -0
- /package/dist/web/assets/{monokai-dci_PdCm.js → monokai-DFIooFZT.js} +0 -0
- /package/dist/web/assets/{moonbit-AAzI-Hd-.js → moonbit-DnBSZWGM.js} +0 -0
- /package/dist/web/assets/{move-kwBhnhrG.js → move-CCcL2PfL.js} +0 -0
- /package/dist/web/assets/{narrat-CXww2YQL.js → narrat-BDarg5Lk.js} +0 -0
- /package/dist/web/assets/{nextflow-groovy-CJXsuXGB.js → nextflow-groovy-DrZOeCNW.js} +0 -0
- /package/dist/web/assets/{night-owl-_GD204Wr.js → night-owl-BnZZCK7v.js} +0 -0
- /package/dist/web/assets/{night-owl-light-DNgkw3kl.js → night-owl-light-CEwBsVHS.js} +0 -0
- /package/dist/web/assets/{nix-BgiorKFd.js → nix-amCzOPMR.js} +0 -0
- /package/dist/web/assets/{nord-CaBmcxFC.js → nord-BIs2BC6q.js} +0 -0
- /package/dist/web/assets/{nushell-DUh4UGx1.js → nushell-Y02fo4yw.js} +0 -0
- /package/dist/web/assets/{objective-c-Cl9KU86S.js → objective-c-7xOZtWW1.js} +0 -0
- /package/dist/web/assets/{objective-cpp-DVkIA8A0.js → objective-cpp-eVtjUvVB.js} +0 -0
- /package/dist/web/assets/{ocaml-vvoHTak0.js → ocaml-Bi6ZwqG4.js} +0 -0
- /package/dist/web/assets/{odin-Cyjw8woZ.js → odin-8xf1Y0S9.js} +0 -0
- /package/dist/web/assets/{one-dark-pro-B1cviILi.js → one-dark-pro-hVv-_y_b.js} +0 -0
- /package/dist/web/assets/{one-light-BPGUJeYI.js → one-light-CJJ3MtHt.js} +0 -0
- /package/dist/web/assets/{openscad-BLMdTUU8.js → openscad-B2HcywLk.js} +0 -0
- /package/dist/web/assets/{pascal-i5niy3e7.js → pascal-C7fllV_7.js} +0 -0
- /package/dist/web/assets/{pkl-CuOV7SsU.js → pkl-qvLC1IWP.js} +0 -0
- /package/dist/web/assets/{plastic-Bf_zE5KL.js → plastic-BT1wHZv2.js} +0 -0
- /package/dist/web/assets/{plsql-cfqEtMD3.js → plsql-1MsmdmJD.js} +0 -0
- /package/dist/web/assets/{plus-BM-Ty0fp.js → plus-BhMZqFsN.js} +0 -0
- /package/dist/web/assets/{po-CFJcWgjr.js → po-BigskytD.js} +0 -0
- /package/dist/web/assets/{poimandres-G5YoaIFf.js → poimandres-DuklniF7.js} +0 -0
- /package/dist/web/assets/{polar-rcjs3i9R.js → polar-e2pjN_sp.js} +0 -0
- /package/dist/web/assets/{postcss-CBKY1FTZ.js → postcss-DtAeYjWw.js} +0 -0
- /package/dist/web/assets/{powerquery-Db7SXLbO.js → powerquery-Cr2PtehI.js} +0 -0
- /package/dist/web/assets/{powershell-LFy3MUTP.js → powershell-BxFTGLJ4.js} +0 -0
- /package/dist/web/assets/{prisma-BE8GR1lH.js → prisma-COWJiwdZ.js} +0 -0
- /package/dist/web/assets/{prolog-DOn5lR1e.js → prolog-DFvGKRx6.js} +0 -0
- /package/dist/web/assets/{proto-wr-TpAK_.js → proto-CcK80lFt.js} +0 -0
- /package/dist/web/assets/{puppet-D2Dkv62u.js → puppet-BF60bZ4F.js} +0 -0
- /package/dist/web/assets/{purescript-DvgJgPdy.js → purescript-zL_69MzU.js} +0 -0
- /package/dist/web/assets/{python-C7TlkHhK.js → python-CIwKhfb_.js} +0 -0
- /package/dist/web/assets/{qmldir-CtZMwhcW.js → qmldir-CXNe04Lo.js} +0 -0
- /package/dist/web/assets/{qss-dNZ2btnl.js → qss-C8lAWe6G.js} +0 -0
- /package/dist/web/assets/{r-BlqnNkHS.js → r-CL5ZVL3_.js} +0 -0
- /package/dist/web/assets/{racket-CzRQrGc4.js → racket-BBfh0uh0.js} +0 -0
- /package/dist/web/assets/{raku-BwutWhBF.js → raku-o6E8R5Q3.js} +0 -0
- /package/dist/web/assets/{react-I_EwPIZi.js → react-CBTnT4sY.js} +0 -0
- /package/dist/web/assets/{red-BMXMywmL.js → red-GomRF2Xp.js} +0 -0
- /package/dist/web/assets/{reg-BqOKrIOw.js → reg-_ffDIvx9.js} +0 -0
- /package/dist/web/assets/{regexp-Bero1BN2.js → regexp-Bl5sF65W.js} +0 -0
- /package/dist/web/assets/{rel-BXKWIElA.js → rel-DgMdqDuj.js} +0 -0
- /package/dist/web/assets/{resolve-theme-B9ABAH_3.js → resolve-theme-CRt_7wpd.js} +0 -0
- /package/dist/web/assets/{riscv-BbbBYJBo.js → riscv-8b3-Ye4X.js} +0 -0
- /package/dist/web/assets/{ron-BtVTWW4b.js → ron-DrmU1KHP.js} +0 -0
- /package/dist/web/assets/{rose-pine-hvkvQzvU.js → rose-pine-C_-E2tF1.js} +0 -0
- /package/dist/web/assets/{rose-pine-dawn-D7lwhUei.js → rose-pine-dawn-DEfhNlFH.js} +0 -0
- /package/dist/web/assets/{rose-pine-moon-CoHDmsIw.js → rose-pine-moon-BdvX3gdn.js} +0 -0
- /package/dist/web/assets/{rosmsg-CdaZFgI8.js → rosmsg-B6GhGpd5.js} +0 -0
- /package/dist/web/assets/{rust-Dy2qsphD.js → rust-DmC97M1-.js} +0 -0
- /package/dist/web/assets/{sass-Bz7NVxDb.js → sass-B0tJOHLM.js} +0 -0
- /package/dist/web/assets/{save-C4z1p51e.js → save-CtIGOjmx.js} +0 -0
- /package/dist/web/assets/{scala-sXSwsNyq.js → scala-n8zaFOXv.js} +0 -0
- /package/dist/web/assets/{scheme-DS7TUbN7.js → scheme-BKD9ztBU.js} +0 -0
- /package/dist/web/assets/{sdbl-iISFvIep.js → sdbl-D8gB5-rS.js} +0 -0
- /package/dist/web/assets/{shellscript-BkIl4ApC.js → shellscript-BfXlf_Ao.js} +0 -0
- /package/dist/web/assets/{shield-check-C5laObJv.js → shield-check-B0iGUiOK.js} +0 -0
- /package/dist/web/assets/{shield-off-DULFtyLS.js → shield-off-BNLWBhcq.js} +0 -0
- /package/dist/web/assets/{slack-dark-B1eg0_m2.js → slack-dark-CylEddse.js} +0 -0
- /package/dist/web/assets/{slack-ochin-mdkc1ldu.js → slack-ochin-w8wg8vuC.js} +0 -0
- /package/dist/web/assets/{smalltalk-CORtd03t.js → smalltalk-hiAXA64u.js} +0 -0
- /package/dist/web/assets/{snazzy-light-Bc6Q2G89.js → snazzy-light-BwlV3Xty.js} +0 -0
- /package/dist/web/assets/{solarized-dark-CF83zRXM.js → solarized-dark-vmNGdykz.js} +0 -0
- /package/dist/web/assets/{solarized-light-BoKQZaYU.js → solarized-light-DGv_0JXq.js} +0 -0
- /package/dist/web/assets/{solidity-DOgi1N4w.js → solidity-Y7QSH0B1.js} +0 -0
- /package/dist/web/assets/{sparkles-Dqsf3hq6.js → sparkles-Dh-_J2Rd.js} +0 -0
- /package/dist/web/assets/{splunk-BXfw5ZLy.js → splunk-BtgpLjHi.js} +0 -0
- /package/dist/web/assets/{sql-BcVs-eX4.js → sql-CRHYhOia.js} +0 -0
- /package/dist/web/assets/{ssh-config-CLCtNkkd.js → ssh-config-DOqSs3au.js} +0 -0
- /package/dist/web/assets/{stylus-DdP992aO.js → stylus-crCAEaBT.js} +0 -0
- /package/dist/web/assets/{swift-BnGb6Lgc.js → swift-eE3rT7TC.js} +0 -0
- /package/dist/web/assets/{synthwave-84-cg9264l9.js → synthwave-84-BWy14LBX.js} +0 -0
- /package/dist/web/assets/{system-verilog-GbHpszs3.js → system-verilog-DC0-DZM4.js} +0 -0
- /package/dist/web/assets/{systemd-Dz-bNsDQ.js → systemd-to5p6N8I.js} +0 -0
- /package/dist/web/assets/{table-CHmxuh6M.js → table-Bbc783ko.js} +0 -0
- /package/dist/web/assets/{talonscript-CFIidoBA.js → talonscript-DoTcU8wm.js} +0 -0
- /package/dist/web/assets/{tasl-Cu-TRTKx.js → tasl-cNZvUs95.js} +0 -0
- /package/dist/web/assets/{tcl-DwCHCB1K.js → tcl-mZE8sZH8.js} +0 -0
- /package/dist/web/assets/{terraform-BzZw4T1z.js → terraform-CqHPpIfu.js} +0 -0
- /package/dist/web/assets/{tokyo-night-RKsj2-tv.js → tokyo-night-Tp2rTIZd.js} +0 -0
- /package/dist/web/assets/{toml-CirbOgDP.js → toml-CU_vscgn.js} +0 -0
- /package/dist/web/assets/{tsv-CraRcWdU.js → tsv-ik7iFB9D.js} +0 -0
- /package/dist/web/assets/{tsx-CjFg0lgw.js → tsx-BMvvMKiv.js} +0 -0
- /package/dist/web/assets/{turtle-B-WBIOa6.js → turtle-DBqKCq9o.js} +0 -0
- /package/dist/web/assets/{typescript-MpLarYn1.js → typescript-DXJDmMZZ.js} +0 -0
- /package/dist/web/assets/{typespec-B7QlHMZ_.js → typespec-CBseCMtZ.js} +0 -0
- /package/dist/web/assets/{typst-CcHSKFZj.js → typst-4oY25U9y.js} +0 -0
- /package/dist/web/assets/{use-is-mobile-BXGVvczu.js → use-is-mobile-D1weanbj.js} +0 -0
- /package/dist/web/assets/{utils-DoY4yTP-.js → utils-BNRH507E.js} +0 -0
- /package/dist/web/assets/{v-xTGhWZuD.js → v-BXaZ_1oy.js} +0 -0
- /package/dist/web/assets/{vala-DwebjH3H.js → vala-BImWJE7z.js} +0 -0
- /package/dist/web/assets/{vb-BxJT2RAy.js → vb-CLfj2_sy.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-CU6zIYMB.js → vendor-xterm-_yyu5n32.js} +0 -0
- /package/dist/web/assets/{verilog-CvV6RHPD.js → verilog-BWa8Ed2b.js} +0 -0
- /package/dist/web/assets/{vesper-CY3qd7E_.js → vesper-BGj1cg6m.js} +0 -0
- /package/dist/web/assets/{vhdl-B9ZX-sUL.js → vhdl-mByK7mlx.js} +0 -0
- /package/dist/web/assets/{viml-Y42h_ExQ.js → viml-CugmlW5g.js} +0 -0
- /package/dist/web/assets/{vitesse-black-DkXP6Sv-.js → vitesse-black-vPdpy9TL.js} +0 -0
- /package/dist/web/assets/{vitesse-dark-B9CkIB6r.js → vitesse-dark-BuQK3dUh.js} +0 -0
- /package/dist/web/assets/{vitesse-light-C7DHrJCK.js → vitesse-light-B3nz1XL9.js} +0 -0
- /package/dist/web/assets/{vyper-Cnd9s5j-.js → vyper-DH_GTIHG.js} +0 -0
- /package/dist/web/assets/{wasm-DQE71XTB.js → wasm-C-LF9GjX.js} +0 -0
- /package/dist/web/assets/{wasm-iWe7Fzjc.js → wasm-DfVbVJlW.js} +0 -0
- /package/dist/web/assets/{wenyan-Bc5Pnm9l.js → wenyan-CzQkHyHx.js} +0 -0
- /package/dist/web/assets/{wgsl-D-YUAWkP.js → wgsl-Du_M1DW9.js} +0 -0
- /package/dist/web/assets/{wikitext-DYQDUYf2.js → wikitext-BWN_w5S7.js} +0 -0
- /package/dist/web/assets/{wit-P6u7mfwy.js → wit-BR13v5HD.js} +0 -0
- /package/dist/web/assets/{wolfram-6SXLUqao.js → wolfram-BoXxp_Xl.js} +0 -0
- /package/dist/web/assets/{x-BcqfTY_7.js → x-nhriOX9o.js} +0 -0
- /package/dist/web/assets/{yaml-CQiMLVcZ.js → yaml-DpR_EF-d.js} +0 -0
- /package/dist/web/assets/{zenscript-DFMywo_P.js → zenscript-C-EdUtUd.js} +0 -0
- /package/dist/web/assets/{zig-CtAjaIiF.js → zig-BD4eA5nU.js} +0 -0
|
@@ -1,22 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* TabPool — persistent tab rendering with DOM reparenting.
|
|
3
3
|
*
|
|
4
|
-
* All tab components are mounted ONCE
|
|
5
|
-
*
|
|
6
|
-
* physically moves
|
|
7
|
-
*
|
|
8
|
-
*
|
|
4
|
+
* All tab components are mounted ONCE and never unmounted when moved between panels or
|
|
5
|
+
* split. Each tab gets a wrapper element that is created once and portalled into; a
|
|
6
|
+
* layout effect physically moves that wrapper into the correct panel slot via appendChild
|
|
7
|
+
* (which moves, not clones). Component instances, hooks, and all internal state (xterm
|
|
8
|
+
* buffer, Monaco editor, chat scroll) survive.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
* to
|
|
10
|
+
* A portal is safe here precisely because the container element is stable: the objection
|
|
11
|
+
* to portals is that *changing* a portal's container remounts its children, and nothing
|
|
12
|
+
* ever swaps a wrapper. In exchange React binds its listeners to the wrapper itself, so
|
|
13
|
+
* they travel with the node — including into another document.
|
|
12
14
|
*/
|
|
13
|
-
import {
|
|
14
|
-
import { Loader2 } from "lucide-react";
|
|
15
|
+
import { useState, useEffect, useSyncExternalStore, lazy } from "react";
|
|
15
16
|
import { usePanelStore } from "@/stores/panel-store";
|
|
16
17
|
import { useMountedTabsStore } from "@/stores/mounted-tabs-store";
|
|
17
18
|
import type { TabType } from "@/stores/tab-store";
|
|
18
19
|
import { collectTabEntries, filterMountableEntries } from "./tab-pool-collect";
|
|
19
|
-
import {
|
|
20
|
+
import { slotRegistry } from "./tab-pool-registry";
|
|
21
|
+
import { ReparentingTab } from "./reparenting-tab";
|
|
22
|
+
import { useWindowPanelReconcile } from "./use-window-panel-reconcile";
|
|
23
|
+
|
|
24
|
+
export { registerPanelSlot } from "./tab-pool-registry";
|
|
20
25
|
|
|
21
26
|
// ---------------------------------------------------------------------------
|
|
22
27
|
// Lazy tab components (single source of truth for all tab types)
|
|
@@ -39,59 +44,29 @@ const TAB_COMPONENTS: Record<TabType, React.LazyExoticComponent<React.ComponentT
|
|
|
39
44
|
group: lazy(() => import("@/components/group-chat/group-chat-tab").then((m) => ({ default: m.GroupChatTab }))),
|
|
40
45
|
};
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
register(panelId: string, el: HTMLDivElement | null) {
|
|
53
|
-
if (el) {
|
|
54
|
-
if (this.slots.get(panelId) === el) return;
|
|
55
|
-
this.slots.set(panelId, el);
|
|
56
|
-
} else {
|
|
57
|
-
if (!this.slots.has(panelId)) return;
|
|
58
|
-
this.slots.delete(panelId);
|
|
59
|
-
}
|
|
60
|
-
this.version++;
|
|
61
|
-
this.listeners.forEach((fn) => fn());
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
get(panelId: string): HTMLDivElement | undefined {
|
|
65
|
-
return this.slots.get(panelId);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
subscribe(fn: SlotListener): () => void {
|
|
69
|
-
this.listeners.add(fn);
|
|
70
|
-
return () => this.listeners.delete(fn);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
getVersion(): number {
|
|
74
|
-
return this.version;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const registry = new SlotRegistry();
|
|
79
|
-
|
|
80
|
-
/** Called by EditorPanel to register its content slot */
|
|
81
|
-
export function registerPanelSlot(panelId: string, el: HTMLDivElement | null) {
|
|
82
|
-
registry.register(panelId, el);
|
|
83
|
-
}
|
|
47
|
+
const HIDDEN_CONTAINER_STYLE: React.CSSProperties = {
|
|
48
|
+
position: "fixed",
|
|
49
|
+
top: 0,
|
|
50
|
+
left: 0,
|
|
51
|
+
width: 0,
|
|
52
|
+
height: 0,
|
|
53
|
+
overflow: "hidden",
|
|
54
|
+
pointerEvents: "none",
|
|
55
|
+
visibility: "hidden",
|
|
56
|
+
};
|
|
84
57
|
|
|
85
58
|
// ---------------------------------------------------------------------------
|
|
86
|
-
// TabPool — renders all tabs
|
|
59
|
+
// TabPool — renders all tabs into wrappers parked off-screen, reparents into slots
|
|
87
60
|
// ---------------------------------------------------------------------------
|
|
88
61
|
export function TabPool() {
|
|
89
|
-
|
|
62
|
+
// State, not a ref: a tab's wrapper must be appended to a real element on its very
|
|
63
|
+
// first layout effect, and a parent ref is still null while its children's effects run.
|
|
64
|
+
const [hiddenContainer, setHiddenContainer] = useState<HTMLDivElement | null>(null);
|
|
90
65
|
|
|
91
66
|
// Re-render when slots change (panel mount/unmount)
|
|
92
67
|
useSyncExternalStore(
|
|
93
|
-
(cb) =>
|
|
94
|
-
() =>
|
|
68
|
+
(cb) => slotRegistry.subscribe(cb),
|
|
69
|
+
() => slotRegistry.getVersion(),
|
|
95
70
|
);
|
|
96
71
|
|
|
97
72
|
const panels = usePanelStore((s) => s.panels);
|
|
@@ -99,6 +74,10 @@ export function TabPool() {
|
|
|
99
74
|
const currentProject = usePanelStore((s) => s.currentProject);
|
|
100
75
|
const projectGrids = usePanelStore((s) => s.projectGrids);
|
|
101
76
|
|
|
77
|
+
// Detached tabs and their floating windows are persisted separately, so a reload can
|
|
78
|
+
// restore one without the other; this repairs the mismatch once per project load.
|
|
79
|
+
useWindowPanelReconcile();
|
|
80
|
+
|
|
102
81
|
// Collect tabs from ALL mounted projects (not just active) to preserve
|
|
103
82
|
// tab state across project switches (keep-alive). Each project's
|
|
104
83
|
// PanelLayout stays mounted (CSS hidden), so slots remain registered.
|
|
@@ -133,118 +112,25 @@ export function TabPool() {
|
|
|
133
112
|
}, [visibleKey]);
|
|
134
113
|
|
|
135
114
|
return (
|
|
136
|
-
// Off-screen
|
|
137
|
-
//
|
|
138
|
-
<div ref={
|
|
139
|
-
{
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
// ReparentingTab — mounts once, physically moves between panel slots
|
|
156
|
-
// ---------------------------------------------------------------------------
|
|
157
|
-
interface ReparentingTabProps {
|
|
158
|
-
tabId: string;
|
|
159
|
-
panelId: string;
|
|
160
|
-
type: TabType;
|
|
161
|
-
metadata?: Record<string, unknown>;
|
|
162
|
-
isActive: boolean;
|
|
163
|
-
hiddenContainer: React.RefObject<HTMLDivElement | null>;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
function ReparentingTab({ tabId, panelId, type, metadata, isActive, hiddenContainer }: ReparentingTabProps) {
|
|
167
|
-
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
168
|
-
const Component = TAB_COMPONENTS[type];
|
|
169
|
-
|
|
170
|
-
// On unmount: move wrapper back to hidden container so React's removeChild
|
|
171
|
-
// can find it. Without this, the wrapper stays orphaned in the slot (the DOM
|
|
172
|
-
// patch swallows the NotFoundError) and covers other tabs.
|
|
173
|
-
useLayoutEffect(() => {
|
|
174
|
-
return () => {
|
|
175
|
-
const wrapper = wrapperRef.current;
|
|
176
|
-
const hidden = hiddenContainer.current;
|
|
177
|
-
if (wrapper && hidden && wrapper.parentElement !== hidden) {
|
|
178
|
-
hidden.appendChild(wrapper);
|
|
179
|
-
}
|
|
180
|
-
};
|
|
181
|
-
}, [hiddenContainer]);
|
|
182
|
-
|
|
183
|
-
// Imperatively move the wrapper DOM node into the correct panel slot.
|
|
184
|
-
// appendChild on an already-mounted node moves it (DOM spec — no clone/destroy).
|
|
185
|
-
// useLayoutEffect runs before paint, so the user never sees the off-screen state.
|
|
186
|
-
// No deps — must run every render because React's reconciliation may call
|
|
187
|
-
// insertBefore() to reorder keyed children, moving reparented nodes back
|
|
188
|
-
// to the hidden container. The early-return guard keeps this cheap.
|
|
189
|
-
useLayoutEffect(() => {
|
|
190
|
-
const wrapper = wrapperRef.current;
|
|
191
|
-
const slot = registry.get(panelId);
|
|
192
|
-
if (!wrapper) return;
|
|
193
|
-
|
|
194
|
-
// Panel slot not mounted (e.g., mobile renders only the focused panel).
|
|
195
|
-
// Move wrapper back to hidden container so it doesn't overlap in the wrong slot.
|
|
196
|
-
if (!slot) {
|
|
197
|
-
const hidden = hiddenContainer.current;
|
|
198
|
-
if (hidden && wrapper.parentElement !== hidden) {
|
|
199
|
-
hidden.appendChild(wrapper);
|
|
200
|
-
}
|
|
201
|
-
return;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (wrapper.parentElement === slot) return;
|
|
205
|
-
|
|
206
|
-
// Save scroll positions — appendChild resets them during the DOM move
|
|
207
|
-
const scrollables: { el: Element; top: number; left: number }[] = [];
|
|
208
|
-
wrapper.querySelectorAll("*").forEach((el) => {
|
|
209
|
-
if (el.scrollTop || el.scrollLeft) {
|
|
210
|
-
scrollables.push({ el, top: el.scrollTop, left: el.scrollLeft });
|
|
211
|
-
}
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
slot.appendChild(wrapper);
|
|
215
|
-
|
|
216
|
-
// Restore scroll positions synchronously before paint
|
|
217
|
-
for (const { el, top, left } of scrollables) {
|
|
218
|
-
el.scrollTop = top;
|
|
219
|
-
el.scrollLeft = left;
|
|
220
|
-
}
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
if (!Component) return null;
|
|
224
|
-
|
|
225
|
-
return (
|
|
226
|
-
<div
|
|
227
|
-
ref={wrapperRef}
|
|
228
|
-
className="absolute inset-0"
|
|
229
|
-
style={isActive ? undefined : { display: "none" }}
|
|
230
|
-
data-tab-pool-id={tabId}
|
|
231
|
-
onMouseDownCapture={() => {
|
|
232
|
-
// Tab content is DOM-reparented out of EditorPanel's fiber subtree, so
|
|
233
|
-
// EditorPanel's onMouseDown never sees clicks on the content body. Set
|
|
234
|
-
// focus here where panelId is known — keeps focusedPanelId correct for
|
|
235
|
-
// every tab type. Dock content is excluded so new tabs open in the grid.
|
|
236
|
-
if (panelId !== DOCK_PANEL_ID) usePanelStore.getState().setFocusedPanel(panelId);
|
|
237
|
-
}}
|
|
238
|
-
>
|
|
239
|
-
<Suspense
|
|
240
|
-
fallback={
|
|
241
|
-
<div className="flex items-center justify-center h-full">
|
|
242
|
-
<Loader2 className="size-6 animate-spin text-primary" />
|
|
243
|
-
</div>
|
|
244
|
-
}
|
|
245
|
-
>
|
|
246
|
-
<Component metadata={metadata} tabId={tabId} />
|
|
247
|
-
</Suspense>
|
|
115
|
+
// Off-screen parking spot. Tab wrappers live here until a layout effect moves them
|
|
116
|
+
// into a panel slot, and come back whenever their panel has no slot mounted.
|
|
117
|
+
<div ref={setHiddenContainer} style={HIDDEN_CONTAINER_STYLE}>
|
|
118
|
+
{hiddenContainer &&
|
|
119
|
+
tabEntries.map((entry) => {
|
|
120
|
+
const Component = TAB_COMPONENTS[entry.type];
|
|
121
|
+
if (!Component) return null;
|
|
122
|
+
return (
|
|
123
|
+
<ReparentingTab
|
|
124
|
+
key={entry.tabId}
|
|
125
|
+
tabId={entry.tabId}
|
|
126
|
+
panelId={entry.panelId}
|
|
127
|
+
component={Component}
|
|
128
|
+
metadata={entry.metadata}
|
|
129
|
+
isActive={entry.isActive}
|
|
130
|
+
hiddenContainer={hiddenContainer}
|
|
131
|
+
/>
|
|
132
|
+
);
|
|
133
|
+
})}
|
|
248
134
|
</div>
|
|
249
135
|
);
|
|
250
136
|
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Open in window" — detaches a tab into a floating window, keeping it live.
|
|
3
|
+
*
|
|
4
|
+
* Desktop only: the window layer renders nothing below the md breakpoint, so on a phone
|
|
5
|
+
* the item would move a tab somewhere the user cannot see (a scaled-down window is never
|
|
6
|
+
* the answer — see the mobile-first UI rules).
|
|
7
|
+
*/
|
|
8
|
+
import { ExternalLink } from "lucide-react";
|
|
9
|
+
import { toast } from "sonner";
|
|
10
|
+
import { ContextMenuItem, ContextMenuSeparator } from "@/components/ui/context-menu";
|
|
11
|
+
import { useIsMobile } from "@/hooks/use-is-mobile";
|
|
12
|
+
import { usePanelStore } from "@/stores/panel-store";
|
|
13
|
+
import type { Tab } from "@/stores/tab-store";
|
|
14
|
+
|
|
15
|
+
interface TabPopOutMenuItemProps {
|
|
16
|
+
tab: Tab;
|
|
17
|
+
/** Panel the tab currently lives in — also where it re-docks when the window closes. */
|
|
18
|
+
panelId: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function TabPopOutMenuItem({ tab, panelId }: TabPopOutMenuItemProps) {
|
|
22
|
+
const isMobile = useIsMobile();
|
|
23
|
+
// The monitor already has a window kind of its own; detaching it would open a second,
|
|
24
|
+
// duplicate presentation of the same data.
|
|
25
|
+
if (isMobile || tab.type === "system-monitor") return null;
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<>
|
|
29
|
+
<ContextMenuItem
|
|
30
|
+
onClick={() => {
|
|
31
|
+
const windowId = usePanelStore.getState().popOutTab(tab.id, panelId);
|
|
32
|
+
// The only rejection a desktop user can hit is the shared window cap.
|
|
33
|
+
if (!windowId) toast.error("Too many windows open — close one first");
|
|
34
|
+
}}
|
|
35
|
+
>
|
|
36
|
+
<ExternalLink className="size-3.5 mr-2" />
|
|
37
|
+
Open in window
|
|
38
|
+
</ContextMenuItem>
|
|
39
|
+
<ContextMenuSeparator />
|
|
40
|
+
</>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One-shot repair of the split between detached tabs and their floating windows.
|
|
3
|
+
*
|
|
4
|
+
* The two halves persist to different keys — window geometry is global and restored by
|
|
5
|
+
* the window layer, panels are restored with the project — so a reload can bring back one
|
|
6
|
+
* without the other. Runs once per project load, after the window layer has restored
|
|
7
|
+
* (otherwise every panel would look orphaned), and unconditionally on mobile, where the
|
|
8
|
+
* window layer renders nothing at all and a workspace synced from a desktop would
|
|
9
|
+
* otherwise hide its detached tabs with no way to reach them.
|
|
10
|
+
*/
|
|
11
|
+
import { useEffect, useRef } from "react";
|
|
12
|
+
import { useIsMobile } from "@/hooks/use-is-mobile";
|
|
13
|
+
import { usePanelStore } from "@/stores/panel-store";
|
|
14
|
+
import { persistWindowPanelChange } from "@/stores/window-panel-actions";
|
|
15
|
+
import { reconcileRunKey, reconcileTabHostWindows } from "@/stores/window-panel-reconcile";
|
|
16
|
+
import { useWindowStore } from "@/components/floating-window/window-store";
|
|
17
|
+
|
|
18
|
+
export function useWindowPanelReconcile(): void {
|
|
19
|
+
const isMobile = useIsMobile();
|
|
20
|
+
const currentProject = usePanelStore((s) => s.currentProject);
|
|
21
|
+
const restored = useWindowStore((s) => s.restored);
|
|
22
|
+
const reconciledFor = useRef<string | null>(null);
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (!currentProject) return;
|
|
26
|
+
if (!restored && !isMobile) return;
|
|
27
|
+
const runKey = reconcileRunKey(currentProject, isMobile);
|
|
28
|
+
if (reconciledFor.current === runKey) return;
|
|
29
|
+
reconciledFor.current = runKey;
|
|
30
|
+
|
|
31
|
+
const { panels, grid, focusedPanelId } = usePanelStore.getState();
|
|
32
|
+
// No window layer on mobile ⇒ no window is live ⇒ every detached tab comes home.
|
|
33
|
+
const liveWindowIds = isMobile
|
|
34
|
+
? []
|
|
35
|
+
: Object.values(useWindowStore.getState().windows)
|
|
36
|
+
.filter((w) => w.kind === "tab-host")
|
|
37
|
+
.map((w) => w.id);
|
|
38
|
+
|
|
39
|
+
const result = reconcileTabHostWindows({ panels, grid, focusedPanelId, liveWindowIds });
|
|
40
|
+
if (result.changed) {
|
|
41
|
+
usePanelStore.setState({ panels: result.panels, focusedPanelId: result.focusedPanelId });
|
|
42
|
+
// Both halves: the window-panel blob shrank, and the tabs landed in a grid panel
|
|
43
|
+
// that belongs to the active project's layout.
|
|
44
|
+
persistWindowPanelChange(usePanelStore.getState);
|
|
45
|
+
}
|
|
46
|
+
for (const windowId of result.windowIdsToClose) useWindowStore.getState().close(windowId);
|
|
47
|
+
}, [currentProject, restored, isMobile]);
|
|
48
|
+
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Finder-flavoured unified titlebar: traffic lights left (grey when unfocused, hover
|
|
3
|
-
* reveals the glyph), title centred. Height matches the
|
|
4
|
-
* constant (not the real Finder 38px) so a minimised
|
|
5
|
-
* what `FloatingWindow` reserves for it.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
3
|
+
* reveals the glyph), title centred, picture-in-picture at the right end. Height matches the
|
|
4
|
+
* shared `TITLEBAR_HEIGHT` contract constant (not the real Finder 38px) so a minimised
|
|
5
|
+
* window's collapsed height agrees with what `FloatingWindow` reserves for it.
|
|
6
|
+
*
|
|
7
|
+
* Worn by EVERY window kind, not just the explorer: the frame resolves one skin for all of
|
|
8
|
+
* them. Anything below the titlebar (the explorer's own toolbar row, tinted by `skins.css`)
|
|
9
|
+
* belongs to the window body — the chrome slot is only the titlebar itself.
|
|
8
10
|
*
|
|
9
11
|
* `data-skin` is set here (not only on the explorer body) because this titlebar is a
|
|
10
12
|
* sibling of the body in the window tree — the `--x-*` vars it reads only resolve on an
|
|
@@ -14,6 +16,7 @@
|
|
|
14
16
|
import { Minus, Plus, X } from "lucide-react";
|
|
15
17
|
import { cn } from "@/lib/utils";
|
|
16
18
|
import { TITLEBAR_HEIGHT, type WindowChromeProps } from "@/components/floating-window/window-chrome-contract";
|
|
19
|
+
import { PipCaptionButton } from "@/components/floating-window/pip/pip-caption-button";
|
|
17
20
|
|
|
18
21
|
/** The traffic-light colours, plus the unfocused grey — the documented hardcoded hexes. */
|
|
19
22
|
const LIGHTS = [
|
|
@@ -23,7 +26,7 @@ const LIGHTS = [
|
|
|
23
26
|
] as const;
|
|
24
27
|
|
|
25
28
|
export function MacosWindowChrome({
|
|
26
|
-
title, focused, titlebarProps, onMinimize, onToggleMaximize, onClose,
|
|
29
|
+
id, title, focused, titlebarProps, onMinimize, onToggleMaximize, onClose,
|
|
27
30
|
}: WindowChromeProps) {
|
|
28
31
|
const { className, style, ...rest } = titlebarProps;
|
|
29
32
|
const actions = [onClose, onMinimize, onToggleMaximize];
|
|
@@ -56,14 +59,20 @@ export function MacosWindowChrome({
|
|
|
56
59
|
</button>
|
|
57
60
|
))}
|
|
58
61
|
</div>
|
|
62
|
+
{/* A flex child, not an absolutely centred span: the title is boxed between the
|
|
63
|
+
traffic lights and the caption button, so a long title truncates instead of
|
|
64
|
+
painting over either of them. Centre is a few px off true middle — acceptable. */}
|
|
59
65
|
<span
|
|
60
66
|
className={cn(
|
|
61
|
-
"pointer-events-none
|
|
67
|
+
"pointer-events-none flex-1 min-w-0 truncate text-center text-[13px] px-2",
|
|
62
68
|
focused ? "text-text" : "text-text-2",
|
|
63
69
|
)}
|
|
64
70
|
>
|
|
65
71
|
{title}
|
|
66
72
|
</span>
|
|
73
|
+
<div className="flex items-center pr-2">
|
|
74
|
+
<PipCaptionButton id={id} />
|
|
75
|
+
</div>
|
|
67
76
|
</div>
|
|
68
77
|
);
|
|
69
78
|
}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Windows 11 File Explorer-flavoured titlebar:
|
|
3
|
-
*
|
|
4
|
-
* constant (not the real Win11 32px) so a minimised window's
|
|
5
|
-
* what `FloatingWindow` reserves for it.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
2
|
+
* Windows 11 File Explorer-flavoured titlebar: title left, caption buttons right (46px wide,
|
|
3
|
+
* close hover red), picture-in-picture left of minimize. Height matches the shared
|
|
4
|
+
* `TITLEBAR_HEIGHT` contract constant (not the real Win11 32px) so a minimised window's
|
|
5
|
+
* collapsed height agrees with what `FloatingWindow` reserves for it.
|
|
6
|
+
*
|
|
7
|
+
* Worn by EVERY window kind, not just the explorer: the frame resolves one skin for all of
|
|
8
|
+
* them. Hence the folder glyph is drawn only for `kind === "explorer"` — it is the File
|
|
9
|
+
* Explorer's app icon, and a system monitor wearing it would be a lie. Anything below the
|
|
10
|
+
* titlebar (the explorer's own toolbar row, tinted by `skins.css`) belongs to the window
|
|
11
|
+
* body — the chrome slot is only the titlebar itself.
|
|
8
12
|
*
|
|
9
13
|
* `data-skin` is set here (not only on the explorer body) because this titlebar is a
|
|
10
14
|
* sibling of the body in the window tree — the `--x-*` vars it reads (`--x-titlebar-bg`,
|
|
@@ -14,6 +18,7 @@
|
|
|
14
18
|
import { Minus, Square, Copy, X } from "lucide-react";
|
|
15
19
|
import { cn } from "@/lib/utils";
|
|
16
20
|
import { TITLEBAR_HEIGHT, type WindowChromeProps } from "@/components/floating-window/window-chrome-contract";
|
|
21
|
+
import { PipCaptionButton } from "@/components/floating-window/pip/pip-caption-button";
|
|
17
22
|
import { WindowsFolderIcon } from "./folder-icon-windows";
|
|
18
23
|
|
|
19
24
|
/** Windows metric: 46px wide caption buttons, full titlebar height. */
|
|
@@ -23,7 +28,7 @@ const CAPTION_BUTTON =
|
|
|
23
28
|
const CLOSE_BUTTON = cn(CAPTION_BUTTON, "can-hover:hover:!bg-[#c42b1c] can-hover:hover:!text-white");
|
|
24
29
|
|
|
25
30
|
export function WindowsWindowChrome({
|
|
26
|
-
title, state, focused, titlebarProps, onMinimize, onToggleMaximize, onClose,
|
|
31
|
+
id, kind, title, state, focused, titlebarProps, onMinimize, onToggleMaximize, onClose,
|
|
27
32
|
}: WindowChromeProps) {
|
|
28
33
|
const { className, style, ...rest } = titlebarProps;
|
|
29
34
|
return (
|
|
@@ -39,9 +44,10 @@ export function WindowsWindowChrome({
|
|
|
39
44
|
)}
|
|
40
45
|
>
|
|
41
46
|
<div className="flex flex-1 min-w-0 items-center gap-2 px-2.5 cursor-default">
|
|
42
|
-
<WindowsFolderIcon className="size-4 shrink-0" />
|
|
47
|
+
{kind === "explorer" && <WindowsFolderIcon className="size-4 shrink-0" />}
|
|
43
48
|
<span className={cn("truncate text-[12px]", focused ? "text-text" : "text-text-2")}>{title}</span>
|
|
44
49
|
</div>
|
|
50
|
+
<PipCaptionButton id={id} className={CAPTION_BUTTON} />
|
|
45
51
|
<button type="button" aria-label="Minimize window" className={CAPTION_BUTTON} onClick={onMinimize}>
|
|
46
52
|
<Minus className="size-3.5" />
|
|
47
53
|
</button>
|
|
@@ -3,6 +3,7 @@ import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
|
|
|
3
3
|
import { ContextMenu as ContextMenuPrimitive } from "radix-ui"
|
|
4
4
|
|
|
5
5
|
import { cn } from "@/lib/utils"
|
|
6
|
+
import { usePortalContainer } from "./portal-container-context"
|
|
6
7
|
|
|
7
8
|
function ContextMenu({
|
|
8
9
|
...props
|
|
@@ -27,10 +28,16 @@ function ContextMenuGroup({
|
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
function ContextMenuPortal({
|
|
31
|
+
container,
|
|
30
32
|
...props
|
|
31
33
|
}: React.ComponentProps<typeof ContextMenuPrimitive.Portal>) {
|
|
34
|
+
const contextContainer = usePortalContainer()
|
|
32
35
|
return (
|
|
33
|
-
<ContextMenuPrimitive.Portal
|
|
36
|
+
<ContextMenuPrimitive.Portal
|
|
37
|
+
data-slot="context-menu-portal"
|
|
38
|
+
container={container ?? contextContainer}
|
|
39
|
+
{...props}
|
|
40
|
+
/>
|
|
34
41
|
)
|
|
35
42
|
}
|
|
36
43
|
|
|
@@ -96,7 +103,7 @@ function ContextMenuContent({
|
|
|
96
103
|
...props
|
|
97
104
|
}: React.ComponentProps<typeof ContextMenuPrimitive.Content>) {
|
|
98
105
|
return (
|
|
99
|
-
<
|
|
106
|
+
<ContextMenuPortal>
|
|
100
107
|
<ContextMenuPrimitive.Content
|
|
101
108
|
data-slot="context-menu-content"
|
|
102
109
|
className={cn(
|
|
@@ -105,7 +112,7 @@ function ContextMenuContent({
|
|
|
105
112
|
)}
|
|
106
113
|
{...props}
|
|
107
114
|
/>
|
|
108
|
-
</
|
|
115
|
+
</ContextMenuPortal>
|
|
109
116
|
)
|
|
110
117
|
}
|
|
111
118
|
|
|
@@ -4,6 +4,7 @@ import { Dialog as DialogPrimitive } from "radix-ui"
|
|
|
4
4
|
|
|
5
5
|
import { cn } from "@/lib/utils"
|
|
6
6
|
import { Button } from "@/components/ui/button"
|
|
7
|
+
import { usePortalContainer } from "./portal-container-context"
|
|
7
8
|
|
|
8
9
|
function Dialog({
|
|
9
10
|
...props
|
|
@@ -18,9 +19,17 @@ function DialogTrigger({
|
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
function DialogPortal({
|
|
22
|
+
container,
|
|
21
23
|
...props
|
|
22
24
|
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
23
|
-
|
|
25
|
+
const contextContainer = usePortalContainer()
|
|
26
|
+
return (
|
|
27
|
+
<DialogPrimitive.Portal
|
|
28
|
+
data-slot="dialog-portal"
|
|
29
|
+
container={container ?? contextContainer}
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
)
|
|
24
33
|
}
|
|
25
34
|
|
|
26
35
|
function DialogClose({
|
|
@@ -5,6 +5,7 @@ import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
|
|
|
5
5
|
import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui"
|
|
6
6
|
|
|
7
7
|
import { cn } from "@/lib/utils"
|
|
8
|
+
import { usePortalContainer } from "./portal-container-context"
|
|
8
9
|
|
|
9
10
|
function DropdownMenu({
|
|
10
11
|
...props
|
|
@@ -13,10 +14,16 @@ function DropdownMenu({
|
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
function DropdownMenuPortal({
|
|
17
|
+
container,
|
|
16
18
|
...props
|
|
17
19
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
|
|
20
|
+
const contextContainer = usePortalContainer()
|
|
18
21
|
return (
|
|
19
|
-
<DropdownMenuPrimitive.Portal
|
|
22
|
+
<DropdownMenuPrimitive.Portal
|
|
23
|
+
data-slot="dropdown-menu-portal"
|
|
24
|
+
container={container ?? contextContainer}
|
|
25
|
+
{...props}
|
|
26
|
+
/>
|
|
20
27
|
)
|
|
21
28
|
}
|
|
22
29
|
|
|
@@ -37,7 +44,7 @@ function DropdownMenuContent({
|
|
|
37
44
|
...props
|
|
38
45
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {
|
|
39
46
|
return (
|
|
40
|
-
<
|
|
47
|
+
<DropdownMenuPortal>
|
|
41
48
|
<DropdownMenuPrimitive.Content
|
|
42
49
|
data-slot="dropdown-menu-content"
|
|
43
50
|
sideOffset={sideOffset}
|
|
@@ -47,7 +54,7 @@ function DropdownMenuContent({
|
|
|
47
54
|
)}
|
|
48
55
|
{...props}
|
|
49
56
|
/>
|
|
50
|
-
</
|
|
57
|
+
</DropdownMenuPortal>
|
|
51
58
|
)
|
|
52
59
|
}
|
|
53
60
|
|
|
@@ -11,6 +11,7 @@ import { createPortal } from "react-dom";
|
|
|
11
11
|
import { cn } from "@/lib/utils";
|
|
12
12
|
import { useSwipeToDismiss } from "@/hooks/use-swipe-to-dismiss";
|
|
13
13
|
import { useVisualViewport } from "@/hooks/use-visual-viewport";
|
|
14
|
+
import { usePortalContainer } from "./portal-container-context";
|
|
14
15
|
|
|
15
16
|
/* ------------------------------------------------------------------ */
|
|
16
17
|
/* Core BottomSheet — reusable everywhere */
|
|
@@ -33,6 +34,7 @@ interface BottomSheetProps {
|
|
|
33
34
|
export function BottomSheet({ open, onClose, children, className, zIndex = 50 }: BottomSheetProps) {
|
|
34
35
|
const { dragY, swipeHandlers, dragStyle, backdropOpacity, isDragging } =
|
|
35
36
|
useSwipeToDismiss(onClose);
|
|
37
|
+
const portalContainer = usePortalContainer();
|
|
36
38
|
|
|
37
39
|
// Keyboard-aware geometry. The backdrop deliberately keeps covering the whole
|
|
38
40
|
// layout viewport while only the panel tracks the keyboard: if the two ever
|
|
@@ -89,7 +91,7 @@ export function BottomSheet({ open, onClose, children, className, zIndex = 50 }:
|
|
|
89
91
|
{children}
|
|
90
92
|
</div>
|
|
91
93
|
</div>,
|
|
92
|
-
sheetPortalTarget(),
|
|
94
|
+
sheetPortalTarget(portalContainer),
|
|
93
95
|
);
|
|
94
96
|
}
|
|
95
97
|
|
|
@@ -103,10 +105,11 @@ export function BottomSheet({ open, onClose, children, className, zIndex = 50 }:
|
|
|
103
105
|
* the event fired on (`body`), finds no match, and drops the event — every
|
|
104
106
|
* button inside a dock tab goes dead while native listeners still fire.
|
|
105
107
|
* `#root` carries no styles, so keeping the portal inside it leaves stacking
|
|
106
|
-
* order untouched.
|
|
108
|
+
* order untouched. A caller-supplied `container` (`PortalContainerProvider`)
|
|
109
|
+
* wins over both fallbacks.
|
|
107
110
|
*/
|
|
108
|
-
function sheetPortalTarget(): HTMLElement {
|
|
109
|
-
return document.getElementById("root") ?? document.body;
|
|
111
|
+
function sheetPortalTarget(container?: HTMLElement): HTMLElement {
|
|
112
|
+
return container ?? document.getElementById("root") ?? document.body;
|
|
110
113
|
}
|
|
111
114
|
|
|
112
115
|
/* ------------------------------------------------------------------ */
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { createContext, useContext, type ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Shared portal target for every Radix/portal-based primitive under
|
|
5
|
+
* `components/ui/`. `undefined` means "the document's default target" — Radix
|
|
6
|
+
* primitives fall back to `document.body`, `mobile-bottom-sheet.tsx` falls
|
|
7
|
+
* back to `#root`. Never pass `null`: Radix's `container` prop only applies
|
|
8
|
+
* its own default when the value is `undefined`, and `null` renders no
|
|
9
|
+
* portal at all.
|
|
10
|
+
*
|
|
11
|
+
* With no provider mounted, `usePortalContainer()` returns `undefined` and
|
|
12
|
+
* every primitive behaves exactly as it did before this context existed.
|
|
13
|
+
*/
|
|
14
|
+
const PortalContainerContext = createContext<HTMLElement | undefined>(
|
|
15
|
+
undefined,
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Mounts a portal target for all descendant Radix primitives. Pass
|
|
20
|
+
* `undefined` to explicitly restore the document default (e.g. once a
|
|
21
|
+
* picture-in-picture window closes).
|
|
22
|
+
*/
|
|
23
|
+
export function PortalContainerProvider({
|
|
24
|
+
container,
|
|
25
|
+
children,
|
|
26
|
+
}: {
|
|
27
|
+
container: HTMLElement | undefined;
|
|
28
|
+
children: ReactNode;
|
|
29
|
+
}) {
|
|
30
|
+
return (
|
|
31
|
+
<PortalContainerContext.Provider value={container}>
|
|
32
|
+
{children}
|
|
33
|
+
</PortalContainerContext.Provider>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** The caller-supplied portal container, or `undefined` outside any provider. */
|
|
38
|
+
export function usePortalContainer(): HTMLElement | undefined {
|
|
39
|
+
return useContext(PortalContainerContext);
|
|
40
|
+
}
|