@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.
- package/CHANGELOG.md +18 -0
- package/README.md +81 -23
- 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/.spike/group-protected-probe.ts +0 -21
- package/.spike/s.err +0 -63
- package/.spike/tunnel.err +0 -22
- package/.spike/w.err +0 -28
- 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
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { clampRect, type Bounds, type Rect } from "./window-geometry";
|
|
10
|
+
import { WINDOW_KINDS } from "./window-store-types";
|
|
10
11
|
import type { WindowKind, WindowRuntimeState, WindowVisualState } from "./window-store-types";
|
|
11
12
|
|
|
12
13
|
const STORAGE_KEY = "ppm-windows";
|
|
@@ -20,7 +21,13 @@ export interface PersistedWindow {
|
|
|
20
21
|
payload?: Record<string, unknown>;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Kinds that may come back after a reload. Derived from WINDOW_KINDS so a new kind is
|
|
26
|
+
* restorable by default; `team-member` is the one exclusion, because its body streams a
|
|
27
|
+
* live subagent session that no longer exists after a reload — restoring it would open
|
|
28
|
+
* an empty shell the user never asked for.
|
|
29
|
+
*/
|
|
30
|
+
const RESTORABLE_KINDS: readonly WindowKind[] = WINDOW_KINDS.filter((k) => k !== "team-member");
|
|
24
31
|
const STATES: WindowVisualState[] = ["normal", "maximized", "minimized"];
|
|
25
32
|
|
|
26
33
|
function isRect(v: unknown): v is Rect {
|
|
@@ -79,7 +86,7 @@ export function loadWindowRects(bounds: Bounds): PersistedWindow[] {
|
|
|
79
86
|
for (const item of parsed) {
|
|
80
87
|
if (!item || typeof item !== "object") continue;
|
|
81
88
|
const w = item as Record<string, unknown>;
|
|
82
|
-
if (typeof w.id !== "string" || !
|
|
89
|
+
if (typeof w.id !== "string" || !RESTORABLE_KINDS.includes(w.kind as WindowKind)) continue;
|
|
83
90
|
if (!isRect(w.rect) || !isSerialisable(w.payload)) continue;
|
|
84
91
|
const state = STATES.includes(w.state as WindowVisualState)
|
|
85
92
|
? (w.state as WindowVisualState)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a floating window shows while its body is playing in a picture-in-picture window.
|
|
3
|
+
*
|
|
4
|
+
* It takes the body's place in the frame's flex column — the body element is physically gone
|
|
5
|
+
* from here, so the two never fight over the space — and it stays in the MAIN document on
|
|
6
|
+
* purpose: it is the way back. An empty frame would just read as lost content.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { cn } from "@/lib/utils";
|
|
10
|
+
import type { PipHandle } from "./pip/pip-host";
|
|
11
|
+
|
|
12
|
+
export function WindowPipPlaceholder({ pip, minimized }: { pip: PipHandle; minimized: boolean }) {
|
|
13
|
+
return (
|
|
14
|
+
<div
|
|
15
|
+
className={cn(
|
|
16
|
+
"relative flex-1 min-h-0 flex flex-col items-center justify-center gap-3",
|
|
17
|
+
"rounded-b-[8px] bg-panel text-center px-4",
|
|
18
|
+
minimized && "hidden",
|
|
19
|
+
)}
|
|
20
|
+
>
|
|
21
|
+
<span className="text-xs text-text-2">Playing in picture-in-picture</span>
|
|
22
|
+
<button
|
|
23
|
+
type="button"
|
|
24
|
+
onClick={() => pip.detach()}
|
|
25
|
+
className="min-h-11 min-w-11 px-4 rounded-md border border-border bg-surface-elevated text-sm text-text can-hover:hover:bg-panel-2 transition-colors"
|
|
26
|
+
>
|
|
27
|
+
Bring back
|
|
28
|
+
</button>
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one piece of state a floating window's chrome and its body must agree on, for every
|
|
3
|
+
* window kind.
|
|
4
|
+
*
|
|
5
|
+
* The titlebar and the body are DOM siblings rendered by the window frame, not parent and
|
|
6
|
+
* child, so React context cannot bridge them: the titlebar needs the body element to hand it
|
|
7
|
+
* to the PiP host, and the frame needs the resulting handle to show its placeholder. Both
|
|
8
|
+
* live here, keyed by WINDOW id, and both are dropped in the frame's layout cleanup.
|
|
9
|
+
*
|
|
10
|
+
* A tab is a third party — TabPool renders it through a portal into a slot inside the body,
|
|
11
|
+
* so it reads the handle from here too (by panel id) to point its Radix portals at the PiP
|
|
12
|
+
* document instead of the main one.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { useCallback, useSyncExternalStore } from "react";
|
|
16
|
+
import { windowIdFromPanelId } from "@/stores/panel-utils";
|
|
17
|
+
import type { PipHandle } from "./pip/pip-host";
|
|
18
|
+
|
|
19
|
+
const slots = new Map<string, HTMLElement>();
|
|
20
|
+
const handles = new Map<string, PipHandle>();
|
|
21
|
+
const listeners = new Set<() => void>();
|
|
22
|
+
|
|
23
|
+
/** Publish (or, with `null`, retract) the body element a window would pop out. */
|
|
24
|
+
export function publishWindowSlot(windowId: string, el: HTMLElement | null): void {
|
|
25
|
+
if (el) slots.set(windowId, el);
|
|
26
|
+
else slots.delete(windowId);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** The body element of a mounted window, or null. */
|
|
30
|
+
export function windowSlot(windowId: string): HTMLElement | null {
|
|
31
|
+
return slots.get(windowId) ?? null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Record the PiP handle a window's body is currently living in (`null` clears it). */
|
|
35
|
+
export function setWindowPip(windowId: string, handle: PipHandle | null): void {
|
|
36
|
+
const current = handles.get(windowId) ?? null;
|
|
37
|
+
if (current === handle) return;
|
|
38
|
+
if (handle) handles.set(windowId, handle);
|
|
39
|
+
else handles.delete(windowId);
|
|
40
|
+
for (const notify of listeners) notify();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The PiP handle for a window, or null when its body is docked in the window. */
|
|
44
|
+
export function windowPip(windowId: string | null | undefined): PipHandle | null {
|
|
45
|
+
return windowId ? (handles.get(windowId) ?? null) : null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function subscribe(onChange: () => void): () => void {
|
|
49
|
+
listeners.add(onChange);
|
|
50
|
+
return () => {
|
|
51
|
+
listeners.delete(onChange);
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Re-renders when the window's PiP handle appears or goes away. */
|
|
56
|
+
export function useWindowPip(windowId: string | null | undefined): PipHandle | null {
|
|
57
|
+
const snapshot = useCallback(() => windowPip(windowId), [windowId]);
|
|
58
|
+
return useSyncExternalStore(subscribe, snapshot);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Portal target for a tab rendered into `panelId`: the PiP document's body while that
|
|
63
|
+
* panel's window is popped out, otherwise `undefined` (the document default). Never `null` —
|
|
64
|
+
* Radix reads `null` as "render no portal at all".
|
|
65
|
+
*/
|
|
66
|
+
export function usePipPortalContainer(panelId: string): HTMLElement | undefined {
|
|
67
|
+
const handle = useWindowPip(windowIdFromPanelId(panelId));
|
|
68
|
+
return handle?.pipWindow.document.body;
|
|
69
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single titlebar every floating window wears, whatever its kind.
|
|
3
|
+
*
|
|
4
|
+
* It resolves the active OS skin (Settings override, otherwise the host platform) and
|
|
5
|
+
* delegates to that skin's chrome, so an explorer, a system monitor, a team-member session
|
|
6
|
+
* and a detached tab are visually the same window — the complaint that produced this file
|
|
7
|
+
* was two kinds shipping two different titlebars.
|
|
8
|
+
*
|
|
9
|
+
* `FloatingWindow` renders the chrome directly with no `<Suspense>` around it, so this entry
|
|
10
|
+
* point cannot be `lazy()` the way a window body is: it has to resolve synchronously, which
|
|
11
|
+
* is exactly what a small wrapper component (rather than a whole feature body) affords.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { useExplorerSkin } from "@/components/os-explorer/skins/use-explorer-skin";
|
|
15
|
+
import type { WindowChromeProps } from "./window-chrome-contract";
|
|
16
|
+
|
|
17
|
+
export function WindowSkinChrome(props: WindowChromeProps) {
|
|
18
|
+
const skin = useExplorerSkin();
|
|
19
|
+
const Chrome = skin.chrome;
|
|
20
|
+
return <Chrome {...props} />;
|
|
21
|
+
}
|
|
@@ -2,8 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
import type { Rect } from "./window-geometry";
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Content families the layer can host. The registry maps each kind to its body component.
|
|
7
|
+
* Single source of truth: the persistence layer filters this list instead of repeating it,
|
|
8
|
+
* so a new kind can never be silently dropped on reload.
|
|
9
|
+
*/
|
|
10
|
+
export const WINDOW_KINDS = ["explorer", "team-member", "system-monitor", "tab-host"] as const;
|
|
11
|
+
|
|
12
|
+
export type WindowKind = (typeof WINDOW_KINDS)[number];
|
|
7
13
|
|
|
8
14
|
export type WindowVisualState = "normal" | "maximized" | "minimized";
|
|
9
15
|
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ReparentingTab — one tab component, mounted once, physically moved between panel slots.
|
|
3
|
+
*
|
|
4
|
+
* The wrapper element is created imperatively and never re-created, and the tab renders
|
|
5
|
+
* into it through a portal. That is what makes the node portable: React attaches its
|
|
6
|
+
* event listeners to the portal container itself, so they keep working after the wrapper
|
|
7
|
+
* is moved into a panel slot — including a slot that lives in another document, where
|
|
8
|
+
* the app root's delegated listeners would never match.
|
|
9
|
+
*
|
|
10
|
+
* The wrapper's placement is owned here (hidden container ⇄ slot); its children are owned
|
|
11
|
+
* by React. Nothing outside may re-create the wrapper: a new container element would
|
|
12
|
+
* remount the tab and destroy exactly the state (xterm buffer, Monaco undo stack, chat
|
|
13
|
+
* scroll) this component exists to preserve.
|
|
14
|
+
*/
|
|
15
|
+
import { useLayoutEffect, useRef, Suspense, type LazyExoticComponent, type ComponentType } from "react";
|
|
16
|
+
import { createPortal } from "react-dom";
|
|
17
|
+
import { Loader2 } from "lucide-react";
|
|
18
|
+
import { usePanelStore } from "@/stores/panel-store";
|
|
19
|
+
import { DOCK_PANEL_ID, isWindowPanelId } from "@/stores/panel-utils";
|
|
20
|
+
import { PortalContainerProvider } from "@/components/ui/portal-container-context";
|
|
21
|
+
import { usePipPortalContainer } from "@/components/floating-window/window-pip-registry";
|
|
22
|
+
import { slotRegistry } from "./tab-pool-registry";
|
|
23
|
+
|
|
24
|
+
export interface ReparentingTabProps {
|
|
25
|
+
tabId: string;
|
|
26
|
+
panelId: string;
|
|
27
|
+
component: LazyExoticComponent<ComponentType<{ metadata?: Record<string, unknown>; tabId?: string }>>;
|
|
28
|
+
metadata?: Record<string, unknown>;
|
|
29
|
+
isActive: boolean;
|
|
30
|
+
/** Off-screen parent the wrapper lives in whenever its panel has no slot mounted. */
|
|
31
|
+
hiddenContainer: HTMLDivElement;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function ReparentingTab({
|
|
35
|
+
tabId,
|
|
36
|
+
panelId,
|
|
37
|
+
component: Component,
|
|
38
|
+
metadata,
|
|
39
|
+
isActive,
|
|
40
|
+
hiddenContainer,
|
|
41
|
+
}: ReparentingTabProps) {
|
|
42
|
+
const wrapperRef = useRef<HTMLDivElement | null>(null);
|
|
43
|
+
if (!wrapperRef.current) {
|
|
44
|
+
const el = document.createElement("div");
|
|
45
|
+
el.className = "absolute inset-0";
|
|
46
|
+
el.dataset.tabPoolId = tabId;
|
|
47
|
+
wrapperRef.current = el;
|
|
48
|
+
}
|
|
49
|
+
const wrapper = wrapperRef.current;
|
|
50
|
+
|
|
51
|
+
// Written during render, before any effect, so the click listener below always reads
|
|
52
|
+
// the panel the tab lives in NOW — a re-docked tab must focus its new panel.
|
|
53
|
+
const panelIdRef = useRef(panelId);
|
|
54
|
+
panelIdRef.current = panelId;
|
|
55
|
+
|
|
56
|
+
// Mount the wrapper and own its removal. The listener is native and capturing because
|
|
57
|
+
// the tab content is DOM-reparented out of the panel's fiber subtree: the panel never
|
|
58
|
+
// sees clicks on the content body, so focus is set here, where the panel is known.
|
|
59
|
+
useLayoutEffect(() => {
|
|
60
|
+
if (!wrapper.parentElement) hiddenContainer.appendChild(wrapper);
|
|
61
|
+
const onMouseDown = () => {
|
|
62
|
+
const pid = panelIdRef.current;
|
|
63
|
+
// Off-grid panels are skipped: focus decides where the next tab opens, and it may
|
|
64
|
+
// never land in the dock or inside a floating window.
|
|
65
|
+
if (pid === DOCK_PANEL_ID || isWindowPanelId(pid)) return;
|
|
66
|
+
usePanelStore.getState().setFocusedPanel(pid);
|
|
67
|
+
};
|
|
68
|
+
wrapper.addEventListener("mousedown", onMouseDown, true);
|
|
69
|
+
return () => {
|
|
70
|
+
wrapper.removeEventListener("mousedown", onMouseDown, true);
|
|
71
|
+
wrapper.remove();
|
|
72
|
+
};
|
|
73
|
+
}, [wrapper, hiddenContainer]);
|
|
74
|
+
|
|
75
|
+
useLayoutEffect(() => {
|
|
76
|
+
wrapper.style.display = isActive ? "" : "none";
|
|
77
|
+
}, [wrapper, isActive]);
|
|
78
|
+
|
|
79
|
+
// Imperatively move the wrapper into the correct panel slot.
|
|
80
|
+
// appendChild on an already-mounted node moves it (DOM spec — no clone/destroy).
|
|
81
|
+
// useLayoutEffect runs before paint, so the user never sees the off-screen state.
|
|
82
|
+
// No deps — must run every render because React's reconciliation may call
|
|
83
|
+
// insertBefore() to reorder keyed children, moving reparented nodes back
|
|
84
|
+
// to the hidden container. The early-return guard keeps this cheap.
|
|
85
|
+
useLayoutEffect(() => {
|
|
86
|
+
const slot = slotRegistry.get(panelId);
|
|
87
|
+
|
|
88
|
+
// Panel slot not mounted (e.g., mobile renders only the focused panel).
|
|
89
|
+
// Move wrapper back to hidden container so it doesn't overlap in the wrong slot.
|
|
90
|
+
if (!slot) {
|
|
91
|
+
if (wrapper.parentElement !== hiddenContainer) hiddenContainer.appendChild(wrapper);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (wrapper.parentElement === slot) return;
|
|
96
|
+
|
|
97
|
+
// Save scroll positions — appendChild resets them during the DOM move
|
|
98
|
+
const scrollables: { el: Element; top: number; left: number }[] = [];
|
|
99
|
+
wrapper.querySelectorAll("*").forEach((el) => {
|
|
100
|
+
if (el.scrollTop || el.scrollLeft) {
|
|
101
|
+
scrollables.push({ el, top: el.scrollTop, left: el.scrollLeft });
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
slot.appendChild(wrapper);
|
|
106
|
+
|
|
107
|
+
// Restore scroll positions synchronously before paint
|
|
108
|
+
for (const { el, top, left } of scrollables) {
|
|
109
|
+
el.scrollTop = top;
|
|
110
|
+
el.scrollLeft = left;
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// Portal target for the tab's own dropdowns, tooltips and sheets. It belongs here and
|
|
115
|
+
// not in the floating-window body: the wrapper's React parent is this component, so a
|
|
116
|
+
// provider mounted around the window body would never reach the tab's primitives, and
|
|
117
|
+
// a menu opened in a picture-in-picture window would render in the main one — off
|
|
118
|
+
// screen, unreachable, and stealing the click. `undefined` while docked, which is the
|
|
119
|
+
// document default.
|
|
120
|
+
const portalContainer = usePipPortalContainer(panelId);
|
|
121
|
+
|
|
122
|
+
return createPortal(
|
|
123
|
+
<PortalContainerProvider container={portalContainer}>
|
|
124
|
+
<Suspense
|
|
125
|
+
fallback={
|
|
126
|
+
<div className="flex items-center justify-center h-full">
|
|
127
|
+
<Loader2 className="size-6 animate-spin text-primary" />
|
|
128
|
+
</div>
|
|
129
|
+
}
|
|
130
|
+
>
|
|
131
|
+
<Component metadata={metadata} tabId={tabId} />
|
|
132
|
+
</Suspense>
|
|
133
|
+
</PortalContainerProvider>,
|
|
134
|
+
wrapper,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
@@ -40,6 +40,7 @@ import { useTabOverflow, getHiddenUnreadDirection } from "@/hooks/use-tab-overfl
|
|
|
40
40
|
import { useSettingsStore } from "@/stores/settings-store";
|
|
41
41
|
import { tabRowClass, tabAddButtonClass } from "@/lib/tab-bar-style";
|
|
42
42
|
import { DraggableTab } from "./draggable-tab";
|
|
43
|
+
import { TabPopOutMenuItem } from "./tab-pop-out-menu-item";
|
|
43
44
|
import { cn } from "@/lib/utils";
|
|
44
45
|
import type { Tab } from "@/stores/tab-store";
|
|
45
46
|
import { downloadFile } from "@/lib/file-download";
|
|
@@ -394,6 +395,7 @@ export const TabBar = memo(function TabBar({ panelId }: TabBarProps) {
|
|
|
394
395
|
tagColor={sessionId ? sessionTagMap[sessionId]?.color : undefined}
|
|
395
396
|
extraMenuContent={
|
|
396
397
|
<>
|
|
398
|
+
<TabPopOutMenuItem tab={tab} panelId={effectivePanelId} />
|
|
397
399
|
{dockMoveMenuItems(tab)}
|
|
398
400
|
{compareMenuItems(tab)}
|
|
399
401
|
{sessionId && !notiType && (
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* characterization test proves it by asserting the same outputs.
|
|
12
12
|
*/
|
|
13
13
|
import type { Panel } from "@/stores/panel-utils";
|
|
14
|
-
import { DOCK_PANEL_ID } from "@/stores/panel-utils";
|
|
14
|
+
import { DOCK_PANEL_ID, isWindowPanelId } from "@/stores/panel-utils";
|
|
15
15
|
import type { TabType } from "@/stores/tab-store";
|
|
16
16
|
|
|
17
17
|
export interface TabEntry {
|
|
@@ -98,6 +98,38 @@ export function collectFromDock(
|
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Collect tab entries from the off-grid panels that host detached tabs (`__win__:*`),
|
|
103
|
+
* deduplicating via seenTabs.
|
|
104
|
+
*
|
|
105
|
+
* Without this pass a popped-out tab is in neither a grid nor the dock, so TabPool would
|
|
106
|
+
* mount it nowhere and the floating window would stay empty.
|
|
107
|
+
*
|
|
108
|
+
* WHY no projectId filter: like the dock, a window panel is global — a detached tab stays
|
|
109
|
+
* visible across a project switch, because a window the user pulled out explicitly
|
|
110
|
+
* vanishing on switch reads as data loss.
|
|
111
|
+
*/
|
|
112
|
+
export function collectFromWindowPanels(
|
|
113
|
+
panels: Record<string, Panel>,
|
|
114
|
+
seenTabs: Set<string>,
|
|
115
|
+
tabEntries: TabEntry[],
|
|
116
|
+
): void {
|
|
117
|
+
for (const [panelId, panel] of Object.entries(panels)) {
|
|
118
|
+
if (!isWindowPanelId(panelId)) continue;
|
|
119
|
+
for (const tab of panel.tabs) {
|
|
120
|
+
if (seenTabs.has(tab.id)) continue;
|
|
121
|
+
seenTabs.add(tab.id);
|
|
122
|
+
tabEntries.push({
|
|
123
|
+
tabId: tab.id,
|
|
124
|
+
panelId,
|
|
125
|
+
type: tab.type,
|
|
126
|
+
metadata: tab.metadata,
|
|
127
|
+
isActive: tab.id === panel.activeTabId,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
101
133
|
/**
|
|
102
134
|
* Collect all tab entries across active and non-active projects, returning
|
|
103
135
|
* the full deduplicated list (sorted by tabId for stable ordering).
|
|
@@ -105,7 +137,7 @@ export function collectFromDock(
|
|
|
105
137
|
* Collection order (intentional — determines dedup precedence):
|
|
106
138
|
* 1. Active project's live grid (highest priority)
|
|
107
139
|
* 2. Non-active projects' snapshotted grids (keep-alive)
|
|
108
|
-
* 3.
|
|
140
|
+
* 3. Window panels (__win__:*) and the dock panel (__dock__) (grid wins on collision)
|
|
109
141
|
*
|
|
110
142
|
* This mirrors what TabPool does before passing entries to ReparentingTab.
|
|
111
143
|
*/
|
|
@@ -127,6 +159,10 @@ export function collectTabEntries(
|
|
|
127
159
|
collectFromGrid(projectGrid, projectName, false, panels, seenTabs, tabEntries);
|
|
128
160
|
}
|
|
129
161
|
|
|
162
|
+
// Off-grid panels last, so a tab that is briefly in both a grid panel and an off-grid
|
|
163
|
+
// one (mid-move) renders in the grid slot the user just dropped it into.
|
|
164
|
+
collectFromWindowPanels(panels, seenTabs, tabEntries);
|
|
165
|
+
|
|
130
166
|
// Dock panel — collected last so grid tabs always win dedup.
|
|
131
167
|
// Missing __dock__ (e.g. legacy state, tests without dock) is safe to skip.
|
|
132
168
|
const dockPanel = panels[DOCK_PANEL_ID];
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slot registry — panels publish the element their tab content should live in.
|
|
3
|
+
*
|
|
4
|
+
* Split out of tab-pool.tsx so the pool and the reparenting wrapper can both reach it
|
|
5
|
+
* without importing each other.
|
|
6
|
+
*
|
|
7
|
+
* Registering an element is a subscription event, not a render input: TabPool subscribes
|
|
8
|
+
* through useSyncExternalStore, so a panel mounting late still gets its tab moved in.
|
|
9
|
+
*/
|
|
10
|
+
type SlotListener = () => void;
|
|
11
|
+
|
|
12
|
+
class SlotRegistry {
|
|
13
|
+
private slots = new Map<string, HTMLDivElement>();
|
|
14
|
+
private listeners = new Set<SlotListener>();
|
|
15
|
+
private version = 0;
|
|
16
|
+
|
|
17
|
+
register(panelId: string, el: HTMLDivElement | null) {
|
|
18
|
+
if (el) {
|
|
19
|
+
if (this.slots.get(panelId) === el) return;
|
|
20
|
+
this.slots.set(panelId, el);
|
|
21
|
+
} else {
|
|
22
|
+
if (!this.slots.has(panelId)) return;
|
|
23
|
+
this.slots.delete(panelId);
|
|
24
|
+
}
|
|
25
|
+
this.version++;
|
|
26
|
+
this.listeners.forEach((fn) => fn());
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get(panelId: string): HTMLDivElement | undefined {
|
|
30
|
+
return this.slots.get(panelId);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
subscribe(fn: SlotListener): () => void {
|
|
34
|
+
this.listeners.add(fn);
|
|
35
|
+
return () => this.listeners.delete(fn);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
getVersion(): number {
|
|
39
|
+
return this.version;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const slotRegistry = new SlotRegistry();
|
|
44
|
+
|
|
45
|
+
/** Called by a panel (grid, dock or floating window) to register its content slot. */
|
|
46
|
+
export function registerPanelSlot(panelId: string, el: HTMLDivElement | null) {
|
|
47
|
+
slotRegistry.register(panelId, el);
|
|
48
|
+
}
|