@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
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Moves an existing DOM subtree (a TabPool panel slot) into a Document
|
|
3
|
+
* Picture-in-Picture window and puts it back.
|
|
4
|
+
*
|
|
5
|
+
* The slot is *moved*, never cloned or remounted: TabPool keeps moving its tab
|
|
6
|
+
* wrapper into whatever element is registered for that panel id, so moving the
|
|
7
|
+
* slot itself leaves that invariant intact and needs no store awareness here.
|
|
8
|
+
* This module imports no store.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { documentPipApi } from "./pip-support";
|
|
12
|
+
import { clampPipSize } from "./pip-geometry";
|
|
13
|
+
import { copyDocumentStyles, syncThemeToPip, watchStyleInjection } from "./pip-style-copy";
|
|
14
|
+
import { forwardKeyEvents } from "./pip-key-forward";
|
|
15
|
+
import { signalHostResize } from "./pip-resize-signal";
|
|
16
|
+
|
|
17
|
+
export interface PipHostOptions {
|
|
18
|
+
/** Requested inner size in CSS px; clamped by clampPipSize(). */
|
|
19
|
+
width: number;
|
|
20
|
+
height: number;
|
|
21
|
+
/** Called after the slot has been restored, for any reason (user close, replacement, error). */
|
|
22
|
+
onDetach(): void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface PipHandle {
|
|
26
|
+
detach(): void;
|
|
27
|
+
readonly pipWindow: Window;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** One PiP window per page — the browser allows no more. */
|
|
31
|
+
let activeHandle: PipHandle | null = null;
|
|
32
|
+
|
|
33
|
+
/** The host currently holding a slot, or null. */
|
|
34
|
+
export function activePipHost(): PipHandle | null {
|
|
35
|
+
return activeHandle;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function setUpHost(
|
|
39
|
+
slotEl: HTMLElement,
|
|
40
|
+
origin: HTMLElement,
|
|
41
|
+
pipWindow: Window,
|
|
42
|
+
opts: PipHostOptions,
|
|
43
|
+
): PipHandle {
|
|
44
|
+
const disposers: Array<() => void> = [];
|
|
45
|
+
let detached = false;
|
|
46
|
+
|
|
47
|
+
const restore = () => {
|
|
48
|
+
if (detached) return;
|
|
49
|
+
detached = true;
|
|
50
|
+
if (activeHandle === handle) activeHandle = null;
|
|
51
|
+
for (const dispose of disposers) {
|
|
52
|
+
try {
|
|
53
|
+
dispose();
|
|
54
|
+
} catch {
|
|
55
|
+
// Keep tearing down — a failed disposer must not strand the slot.
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Synchronous on purpose: letting the PiP document close with the subtree
|
|
59
|
+
// still inside strips every DOM listener in it recursively, which kills a
|
|
60
|
+
// live terminal for good. No await, no rAF between here and the move.
|
|
61
|
+
if (origin.isConnected) {
|
|
62
|
+
origin.append(slotEl);
|
|
63
|
+
signalHostResize(slotEl);
|
|
64
|
+
}
|
|
65
|
+
try {
|
|
66
|
+
pipWindow.close();
|
|
67
|
+
} catch {
|
|
68
|
+
// Already closing.
|
|
69
|
+
}
|
|
70
|
+
opts.onDetach();
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const handle: PipHandle = { detach: restore, pipWindow };
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
const doc = pipWindow.document;
|
|
77
|
+
copyDocumentStyles(document, doc);
|
|
78
|
+
disposers.push(syncThemeToPip(document, doc));
|
|
79
|
+
disposers.push(watchStyleInjection(document, doc));
|
|
80
|
+
|
|
81
|
+
doc.body.append(slotEl);
|
|
82
|
+
signalHostResize(slotEl);
|
|
83
|
+
|
|
84
|
+
// The PiP window's own resize fires immediately, unlike the main window's
|
|
85
|
+
// ResizeObservers for a PiP-driven size.
|
|
86
|
+
const onPipResize = () => signalHostResize(slotEl);
|
|
87
|
+
pipWindow.addEventListener("resize", onPipResize);
|
|
88
|
+
disposers.push(() => pipWindow.removeEventListener("resize", onPipResize));
|
|
89
|
+
|
|
90
|
+
pipWindow.addEventListener("pagehide", restore);
|
|
91
|
+
disposers.push(() => pipWindow.removeEventListener("pagehide", restore));
|
|
92
|
+
|
|
93
|
+
disposers.push(forwardKeyEvents(pipWindow, window));
|
|
94
|
+
|
|
95
|
+
// The main window going away must not leave the slot in a dying document.
|
|
96
|
+
window.addEventListener("pagehide", restore);
|
|
97
|
+
window.addEventListener("beforeunload", restore);
|
|
98
|
+
disposers.push(() => {
|
|
99
|
+
window.removeEventListener("pagehide", restore);
|
|
100
|
+
window.removeEventListener("beforeunload", restore);
|
|
101
|
+
});
|
|
102
|
+
} catch (err) {
|
|
103
|
+
restore();
|
|
104
|
+
throw err;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return handle;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Open a PiP window and move `slotEl` into it.
|
|
112
|
+
*
|
|
113
|
+
* `requestWindow()` needs transient activation, and it is the first async call
|
|
114
|
+
* here — call this synchronously from a click handler, with nothing awaited
|
|
115
|
+
* before it.
|
|
116
|
+
*
|
|
117
|
+
* Resolves to `null` when the slot went away while the request was in flight;
|
|
118
|
+
* that is the user closing the window mid-request, not a failure.
|
|
119
|
+
*/
|
|
120
|
+
export async function attachPipHost(slotEl: HTMLElement, opts: PipHostOptions): Promise<PipHandle | null> {
|
|
121
|
+
const api = documentPipApi();
|
|
122
|
+
if (!api) throw new Error("Document Picture-in-Picture is not supported in this browser");
|
|
123
|
+
const origin = slotEl.parentElement;
|
|
124
|
+
if (!origin) throw new Error("attachPipHost: slot element must be in the document");
|
|
125
|
+
|
|
126
|
+
// One PiP at a time: the previous tab goes back to its floating window first.
|
|
127
|
+
activeHandle?.detach();
|
|
128
|
+
|
|
129
|
+
let pipWindow: Window;
|
|
130
|
+
try {
|
|
131
|
+
pipWindow = await api.requestWindow(clampPipSize({ width: opts.width, height: opts.height }));
|
|
132
|
+
} catch (err) {
|
|
133
|
+
// Rejected (usually: no transient activation left). Nothing moved, but the
|
|
134
|
+
// caller still has to drop the "in PiP" state it optimistically set.
|
|
135
|
+
opts.onDetach();
|
|
136
|
+
throw err;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// The window can close while the request is pending: its body unmounts, the tab is
|
|
140
|
+
// re-docked and the slot is dropped from the document. Moving it now would hand an
|
|
141
|
+
// orphaned subtree to a PiP window nobody owns, and register a handle under a dead
|
|
142
|
+
// window id. Proceed only if the slot is still exactly where it was.
|
|
143
|
+
if (!slotEl.isConnected || slotEl.parentElement !== origin) {
|
|
144
|
+
try {
|
|
145
|
+
pipWindow.close();
|
|
146
|
+
} catch {
|
|
147
|
+
// Already closing.
|
|
148
|
+
}
|
|
149
|
+
opts.onDetach();
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const handle = setUpHost(slotEl, origin, pipWindow, opts);
|
|
154
|
+
activeHandle = handle;
|
|
155
|
+
return handle;
|
|
156
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Forward keyboard events from a PiP window to the main window.
|
|
3
|
+
*
|
|
4
|
+
* The app's global shortcuts are bound once on the main `window` and cannot be
|
|
5
|
+
* re-bound from outside, so events that originate in the PiP document are
|
|
6
|
+
* cloned and re-dispatched there.
|
|
7
|
+
*
|
|
8
|
+
* Two limits are deliberate:
|
|
9
|
+
* - `preventDefault()` on the clone does NOT suppress the original event's
|
|
10
|
+
* browser default inside the PiP. Forwarding is one-way; never rely on the
|
|
11
|
+
* clone to cancel anything.
|
|
12
|
+
* - Targets that own their keyboard handling are skipped, so a shortcut does
|
|
13
|
+
* not fire while the user is typing. Monaco's EditContext host is a `div`
|
|
14
|
+
* (`.native-edit-context`), not an input, and xterm listens on its helper
|
|
15
|
+
* textarea — both must be in the skip list.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export const SKIP_SELECTOR = [
|
|
19
|
+
"input",
|
|
20
|
+
"textarea",
|
|
21
|
+
"select",
|
|
22
|
+
"[contenteditable]",
|
|
23
|
+
".native-edit-context",
|
|
24
|
+
".monaco-editor",
|
|
25
|
+
".xterm-helper-textarea",
|
|
26
|
+
].join(", ");
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Whether the event's target owns its own keyboard input, in which case the event is
|
|
30
|
+
* the user typing and must not be forwarded as a shortcut.
|
|
31
|
+
*
|
|
32
|
+
* PiP-created nodes live in another realm, so `instanceof Element` is unsafe; the
|
|
33
|
+
* duck-typed `closest` is the check. A target that cannot answer is not editable —
|
|
34
|
+
* the PiP `window` itself is the common one.
|
|
35
|
+
*/
|
|
36
|
+
export function isEditableTarget(target: EventTarget | null): boolean {
|
|
37
|
+
const el = target as Element | null;
|
|
38
|
+
if (!el || typeof el.closest !== "function") return false;
|
|
39
|
+
return el.closest(SKIP_SELECTOR) !== null;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Clone `keydown`/`keyup` from `from` onto `to`. Returns an unsubscribe.
|
|
44
|
+
* Only events originating in `from` are forwarded, so the main window never
|
|
45
|
+
* sees its own events twice.
|
|
46
|
+
*/
|
|
47
|
+
export function forwardKeyEvents(from: Window, to: Window): () => void {
|
|
48
|
+
const handler = (event: Event) => {
|
|
49
|
+
const keyEvent = event as KeyboardEvent;
|
|
50
|
+
if (isEditableTarget(keyEvent.target)) return;
|
|
51
|
+
to.dispatchEvent(new KeyboardEvent(keyEvent.type, keyEvent));
|
|
52
|
+
};
|
|
53
|
+
from.addEventListener("keydown", handler);
|
|
54
|
+
from.addEventListener("keyup", handler);
|
|
55
|
+
return () => {
|
|
56
|
+
from.removeEventListener("keydown", handler);
|
|
57
|
+
from.removeEventListener("keyup", handler);
|
|
58
|
+
};
|
|
59
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resize signal for tabs whose host document changed size.
|
|
3
|
+
*
|
|
4
|
+
* Main-window `ResizeObserver`s are late (xterm: seconds) or silent (Monaco
|
|
5
|
+
* `automaticLayout`) for sizes driven by a PiP window, so the host tells the
|
|
6
|
+
* tabs directly instead of waiting for an observer.
|
|
7
|
+
*
|
|
8
|
+
* The event does NOT bubble: it is dispatched on every tab wrapper inside the
|
|
9
|
+
* slot, and the slot is an *ancestor* of those wrappers — an upward-bubbling
|
|
10
|
+
* event dispatched on the slot would never reach them.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export const HOST_RESIZE_EVENT = "ppm:host-resize";
|
|
14
|
+
|
|
15
|
+
/** Tell every tab inside `slotEl` that its host size changed. */
|
|
16
|
+
export function signalHostResize(slotEl: Element | null | undefined): void {
|
|
17
|
+
if (!slotEl) return;
|
|
18
|
+
for (const wrapper of slotEl.querySelectorAll("[data-tab-pool-id]")) {
|
|
19
|
+
wrapper.dispatchEvent(new CustomEvent(HOST_RESIZE_EVENT, { bubbles: false }));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Subscribe a tab surface to the signal. `containerEl` is any node inside the
|
|
25
|
+
* tab; the listener lands on its `[data-tab-pool-id]` wrapper. Returns an
|
|
26
|
+
* unsubscribe (a no-op when the element is not inside a pooled tab).
|
|
27
|
+
*/
|
|
28
|
+
export function onHostResize(containerEl: Element | null | undefined, handler: () => void): () => void {
|
|
29
|
+
const wrapper = containerEl?.closest("[data-tab-pool-id]");
|
|
30
|
+
if (!wrapper) return () => {};
|
|
31
|
+
wrapper.addEventListener(HOST_RESIZE_EVENT, handler);
|
|
32
|
+
return () => wrapper.removeEventListener(HOST_RESIZE_EVENT, handler);
|
|
33
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Style/theme bootstrap for a PiP document.
|
|
3
|
+
*
|
|
4
|
+
* A PiP window is a separate document: it inherits no stylesheet and no theme.
|
|
5
|
+
* Copying `styleSheets` alone still yields an unthemed window, because the
|
|
6
|
+
* theme is written as inline CSS custom properties on `<html>` — the class and
|
|
7
|
+
* the inline `cssText` must both be mirrored, and re-mirrored on every theme
|
|
8
|
+
* change.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { THEME_CHANGE_EVENT } from "@/theme/apply-theme";
|
|
12
|
+
|
|
13
|
+
const STYLE_NODE_SELECTOR = 'style, link[rel="stylesheet"]';
|
|
14
|
+
|
|
15
|
+
/** Body/slot layout for the PiP document — the slot is the only child. */
|
|
16
|
+
const PIP_BASE_CSS = `html,body{margin:0;padding:0;width:100%;height:100%;overflow:hidden}
|
|
17
|
+
body>*{position:relative;width:100%;height:100%}`;
|
|
18
|
+
|
|
19
|
+
/** Minimal document shape needed to enumerate style nodes (keeps this pure). */
|
|
20
|
+
export interface StyleNodeSource {
|
|
21
|
+
querySelectorAll(selectors: string): ArrayLike<Element>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Ordered list of the `<style>` / `<link rel=stylesheet>` nodes to mirror. */
|
|
25
|
+
export function collectStyleNodes(doc: StyleNodeSource): Element[] {
|
|
26
|
+
return Array.from(doc.querySelectorAll(STYLE_NODE_SELECTOR));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Mirror one style node into `dst`. Same-origin sheets are inlined from their
|
|
31
|
+
* parsed rules (no refetch); a cross-origin sheet throws on `cssRules`, so the
|
|
32
|
+
* `<link>` is cloned and the PiP window fetches it itself.
|
|
33
|
+
*/
|
|
34
|
+
function mirrorStyleNode(node: Element, dst: Document): void {
|
|
35
|
+
const sheet = (node as HTMLStyleElement | HTMLLinkElement).sheet;
|
|
36
|
+
try {
|
|
37
|
+
const rules = sheet?.cssRules;
|
|
38
|
+
if (rules && rules.length > 0) {
|
|
39
|
+
const style = dst.createElement("style");
|
|
40
|
+
style.textContent = Array.from(rules, (rule) => rule.cssText).join("\n");
|
|
41
|
+
dst.head.append(style);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
} catch {
|
|
45
|
+
// Cross-origin sheet — fall through to cloning the element.
|
|
46
|
+
}
|
|
47
|
+
dst.head.append(node.cloneNode(true));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Copy every stylesheet of `src` into `dst`, plus the PiP base layout. */
|
|
51
|
+
export function copyDocumentStyles(src: Document, dst: Document): void {
|
|
52
|
+
try {
|
|
53
|
+
// Constructed sheets are per-document; adopting a foreign one can throw.
|
|
54
|
+
dst.adoptedStyleSheets = [...src.adoptedStyleSheets];
|
|
55
|
+
} catch {
|
|
56
|
+
// Ignore — the cloned nodes below still carry the app's CSS.
|
|
57
|
+
}
|
|
58
|
+
for (const node of collectStyleNodes(src)) mirrorStyleNode(node, dst);
|
|
59
|
+
const base = dst.createElement("style");
|
|
60
|
+
base.textContent = PIP_BASE_CSS;
|
|
61
|
+
dst.head.append(base);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Copy `<html>` class + inline theme vars and `<body>` class + inline style, once.
|
|
66
|
+
* The page background is an inline `background: var(--bg)` on `<body>` (index.html),
|
|
67
|
+
* not a class — without it the PiP body stays browser-default white and every
|
|
68
|
+
* transparent region of the moved tab shows through as light.
|
|
69
|
+
*/
|
|
70
|
+
function copyThemeOnce(src: Document, dst: Document): void {
|
|
71
|
+
dst.documentElement.className = src.documentElement.className;
|
|
72
|
+
dst.documentElement.style.cssText = src.documentElement.style.cssText;
|
|
73
|
+
dst.body.className = src.body.className;
|
|
74
|
+
dst.body.style.cssText = src.body.style.cssText;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Mirror the theme now and on every theme change. Returns a disposer that
|
|
79
|
+
* unsubscribes.
|
|
80
|
+
*/
|
|
81
|
+
export function syncThemeToPip(src: Document, dst: Document): () => void {
|
|
82
|
+
copyThemeOnce(src, dst);
|
|
83
|
+
const view = src.defaultView;
|
|
84
|
+
if (!view) return () => {};
|
|
85
|
+
const onThemeChange = () => copyThemeOnce(src, dst);
|
|
86
|
+
view.addEventListener(THEME_CHANGE_EVENT, onThemeChange);
|
|
87
|
+
return () => view.removeEventListener(THEME_CHANGE_EVENT, onThemeChange);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Mirror stylesheets injected into `src.head` after the copy — Vite dev/HMR
|
|
92
|
+
* appends a new `<style>` on every edit, which the PiP copy would otherwise
|
|
93
|
+
* never see. Harmless in production. Returns a disposer.
|
|
94
|
+
*/
|
|
95
|
+
export function watchStyleInjection(src: Document, dst: Document): () => void {
|
|
96
|
+
if (typeof MutationObserver === "undefined") return () => {};
|
|
97
|
+
const observer = new MutationObserver((records) => {
|
|
98
|
+
for (const record of records) {
|
|
99
|
+
for (const added of record.addedNodes) {
|
|
100
|
+
if (added instanceof Element && added.matches(STYLE_NODE_SELECTOR)) {
|
|
101
|
+
dst.head.append(added.cloneNode(true));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
observer.observe(src.head, { childList: true });
|
|
107
|
+
return () => observer.disconnect();
|
|
108
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feature probe for the Document Picture-in-Picture API.
|
|
3
|
+
*
|
|
4
|
+
* `lib.dom` does not type `documentPictureInPicture` yet, so the minimal shape
|
|
5
|
+
* the host actually uses is declared here and nowhere else.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface DocumentPictureInPictureOptions {
|
|
9
|
+
width?: number;
|
|
10
|
+
height?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface DocumentPictureInPictureApi {
|
|
14
|
+
requestWindow(options?: DocumentPictureInPictureOptions): Promise<Window>;
|
|
15
|
+
readonly window: Window | null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
declare global {
|
|
19
|
+
interface Window {
|
|
20
|
+
documentPictureInPicture?: DocumentPictureInPictureApi;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** True when this browser can open a Document PiP window (Chromium >= 116). */
|
|
25
|
+
export function isDocumentPipSupported(): boolean {
|
|
26
|
+
return typeof window !== "undefined" && "documentPictureInPicture" in window;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** The API object, or null when unsupported — keeps the cast in one place. */
|
|
30
|
+
export function documentPipApi(): DocumentPictureInPictureApi | null {
|
|
31
|
+
if (!isDocumentPipSupported()) return null;
|
|
32
|
+
return window.documentPictureInPicture ?? null;
|
|
33
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Floating-window body that hosts a detached tab.
|
|
3
|
+
*
|
|
4
|
+
* It renders no tab of its own: it publishes a TabPool slot, and TabPool moves the tab's
|
|
5
|
+
* live DOM node into it. That is the whole point — the terminal keeps its PTY, the editor
|
|
6
|
+
* its undo stack, the chat its stream, because nothing remounts.
|
|
7
|
+
*
|
|
8
|
+
* Picture-in-picture is not handled here: the frame publishes its own body element as the
|
|
9
|
+
* PiP slot and owns the placeholder, so this file only has to hand the tab back when it
|
|
10
|
+
* goes away.
|
|
11
|
+
*/
|
|
12
|
+
import { useCallback, useLayoutEffect, useRef } from "react";
|
|
13
|
+
import { usePanelStore } from "@/stores/panel-store";
|
|
14
|
+
import { windowPanelId } from "@/stores/panel-utils";
|
|
15
|
+
import { registerPanelSlot } from "@/components/layout/tab-pool";
|
|
16
|
+
import type { WindowContentProps } from "./window-content-registry";
|
|
17
|
+
|
|
18
|
+
export default function TabHostWindowContent({ id, payload }: WindowContentProps) {
|
|
19
|
+
// Derived, never passed in: the window id is minted by the store's open() call, so the
|
|
20
|
+
// panel id cannot exist before the window does.
|
|
21
|
+
const panelId = windowPanelId(id);
|
|
22
|
+
const panel = usePanelStore((s) => s.panels[panelId]);
|
|
23
|
+
const hasTabs = (panel?.tabs.length ?? 0) > 0;
|
|
24
|
+
|
|
25
|
+
// A window restored from a previous session exists before the project layout finishes
|
|
26
|
+
// loading. Remembering that a tab was once here keeps the placeholder from flashing
|
|
27
|
+
// back when the tab is legitimately on its way out.
|
|
28
|
+
const everHadTabs = useRef(false);
|
|
29
|
+
if (hasTabs) everHadTabs.current = true;
|
|
30
|
+
|
|
31
|
+
const originPanelId = typeof payload?.originPanelId === "string" ? payload.originPanelId : null;
|
|
32
|
+
const originRef = useRef(originPanelId);
|
|
33
|
+
originRef.current = originPanelId;
|
|
34
|
+
|
|
35
|
+
const slotRef = useCallback(
|
|
36
|
+
(el: HTMLDivElement | null) => registerPanelSlot(panelId, el),
|
|
37
|
+
[panelId],
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
// Re-dock when this body goes away. Every close path (titlebar ×, keyboard, a
|
|
41
|
+
// programmatic close, the window layer unmounting below the desktop breakpoint) unmounts
|
|
42
|
+
// this body, so they all route through here. The frame's own layout cleanup has already
|
|
43
|
+
// taken the body out of any PiP document by this point — React destroys a parent's layout
|
|
44
|
+
// effects before its children's — so the tab is back in the main document to be moved.
|
|
45
|
+
//
|
|
46
|
+
// The hand-back is deferred by one microtask on purpose: React StrictMode (and Offscreen /
|
|
47
|
+
// Activity subtrees) run a layout cleanup and then immediately re-run the setup on the
|
|
48
|
+
// SAME instance. Re-docking synchronously in that simulated cleanup pulled the tab back
|
|
49
|
+
// to the grid a moment after every pop-out and left the window empty. A re-run setup
|
|
50
|
+
// cancels the pending hand-back; a real unmount has no re-run, so the microtask fires.
|
|
51
|
+
// Deferring is safe for the DOM: React only detaches this body's root node, the slot and
|
|
52
|
+
// the tab inside it stay intact until the microtask runs.
|
|
53
|
+
const pendingRedock = useRef<object | null>(null);
|
|
54
|
+
useLayoutEffect(() => {
|
|
55
|
+
pendingRedock.current = null;
|
|
56
|
+
return () => {
|
|
57
|
+
const token = {};
|
|
58
|
+
pendingRedock.current = token;
|
|
59
|
+
queueMicrotask(() => {
|
|
60
|
+
if (pendingRedock.current !== token) return;
|
|
61
|
+
pendingRedock.current = null;
|
|
62
|
+
usePanelStore.getState().redockFromWindow(id, originRef.current);
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
}, [id]);
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<div className="relative h-full w-full">
|
|
69
|
+
{/* Always mounted, never swapped for a placeholder: the slot may currently hold a
|
|
70
|
+
reparented tab (or live in another document), and unmounting it would make React
|
|
71
|
+
remove a node whose parent is no longer this tree. */}
|
|
72
|
+
<div ref={slotRef} className="absolute inset-0" />
|
|
73
|
+
{!hasTabs && !everHadTabs.current && (
|
|
74
|
+
<div className="absolute inset-0 flex items-center justify-center text-xs text-text-2 pointer-events-none">
|
|
75
|
+
Loading…
|
|
76
|
+
</div>
|
|
77
|
+
)}
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The body element every floating window renders its content into, and its picture-in-picture
|
|
3
|
+
* lifecycle. Owned by the frame, so PiP is a capability of the window rather than of any one
|
|
4
|
+
* kind.
|
|
5
|
+
*
|
|
6
|
+
* The element is created imperatively and never re-created, and the content reaches it
|
|
7
|
+
* through a portal. That is what makes it portable: React attaches its delegated listeners
|
|
8
|
+
* to a portal container, and they travel with the node into another document — a normally
|
|
9
|
+
* rendered subtree goes dead (no clicks, no menus) the moment it is moved into a PiP
|
|
10
|
+
* document.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { useLayoutEffect, useState, type RefObject } from "react";
|
|
14
|
+
import { activePipHost, type PipHandle } from "./pip/pip-host";
|
|
15
|
+
import { publishWindowSlot, useWindowPip, windowPip } from "./window-pip-registry";
|
|
16
|
+
|
|
17
|
+
const BODY_CLASS = "relative flex-1 min-h-0 overflow-hidden rounded-b-[8px] bg-panel";
|
|
18
|
+
|
|
19
|
+
export interface WindowBodyElement {
|
|
20
|
+
/** Portal target for the window's content. */
|
|
21
|
+
body: HTMLElement;
|
|
22
|
+
/** The PiP handle this window's body currently lives in, or null. */
|
|
23
|
+
pip: PipHandle | null;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function useWindowBodyElement(
|
|
27
|
+
windowId: string,
|
|
28
|
+
rootRef: RefObject<HTMLElement | null>,
|
|
29
|
+
minimized: boolean,
|
|
30
|
+
): WindowBodyElement {
|
|
31
|
+
const pip = useWindowPip(windowId);
|
|
32
|
+
const [body] = useState(() => {
|
|
33
|
+
const el = document.createElement("div");
|
|
34
|
+
el.className = BODY_CLASS;
|
|
35
|
+
return el;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Mount the body and publish it as this window's PiP slot.
|
|
39
|
+
//
|
|
40
|
+
// The cleanup is the window's teardown order, and it must run BEFORE the content's own
|
|
41
|
+
// cleanups: React destroys a parent's layout effects before its children's when a subtree
|
|
42
|
+
// is deleted (commitDeletionEffectsOnFiber runs the fiber's own destroys, then recurses
|
|
43
|
+
// into children). So PiP is detached — moving the body out of a document about to close —
|
|
44
|
+
// while the content below is still mounted, and a tab-host body's deferred re-dock still
|
|
45
|
+
// gets to run afterwards on a subtree that is back in the main document.
|
|
46
|
+
useLayoutEffect(() => {
|
|
47
|
+
const root = rootRef.current;
|
|
48
|
+
if (!root) return;
|
|
49
|
+
root.append(body);
|
|
50
|
+
publishWindowSlot(windowId, body);
|
|
51
|
+
return () => {
|
|
52
|
+
const handle = windowPip(windowId);
|
|
53
|
+
if (handle && activePipHost() === handle) handle.detach();
|
|
54
|
+
publishWindowSlot(windowId, null);
|
|
55
|
+
body.remove();
|
|
56
|
+
};
|
|
57
|
+
}, [body, rootRef, windowId]);
|
|
58
|
+
|
|
59
|
+
// Minimising hides the body via CSS rather than unmounting it — content owns per-window
|
|
60
|
+
// state (explorer history, selection, filter) that a remount would wipe. Never while PiP
|
|
61
|
+
// is active: the body is in the PiP document then, and `hidden` would blank it there.
|
|
62
|
+
useLayoutEffect(() => {
|
|
63
|
+
body.classList.toggle("hidden", minimized && !pip);
|
|
64
|
+
}, [body, minimized, pip]);
|
|
65
|
+
|
|
66
|
+
return { body, pip };
|
|
67
|
+
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import { useDrag } from "@use-gesture/react";
|
|
4
4
|
import { clampRect, type Rect } from "./window-geometry";
|
|
5
5
|
import {
|
|
6
|
+
gestureAbandoned,
|
|
6
7
|
gestureDisplacement,
|
|
7
8
|
WINDOW_DRAG_CONFIG,
|
|
8
9
|
type WindowGestureContext,
|
|
@@ -11,6 +12,10 @@ import {
|
|
|
11
12
|
export function useWindowDrag(ctx: WindowGestureContext) {
|
|
12
13
|
return useDrag(
|
|
13
14
|
({ xy, initial, first, last, memo }) => {
|
|
15
|
+
if (gestureAbandoned(first, memo)) {
|
|
16
|
+
if (last) ctx.onGestureActive(false);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
14
19
|
// The rect is captured once per gesture: the displacement is cumulative from the
|
|
15
20
|
// start, so re-reading a rect that we ourselves are mutating would compound it.
|
|
16
21
|
const base: Rect = first ? { ...ctx.getRect() } : (memo as Rect);
|
|
@@ -25,6 +25,20 @@ export const WINDOW_DRAG_CONFIG = {
|
|
|
25
25
|
pointer: { capture: true },
|
|
26
26
|
} as const;
|
|
27
27
|
|
|
28
|
+
/**
|
|
29
|
+
* True when a gesture event arrives with no rect to work from.
|
|
30
|
+
*
|
|
31
|
+
* A gesture can outlive the window it started on: pressing a caption button (close, or
|
|
32
|
+
* anything that unmounts the frame) begins a drag on the titlebar, and @use-gesture still
|
|
33
|
+
* delivers a terminating event afterwards — with `first` false and `memo` undefined, because
|
|
34
|
+
* the frame that would have captured the rect is gone. Reading `memo.x` there is a
|
|
35
|
+
* `TypeError` on every window close. Nothing is left to move or resize, so the gesture is
|
|
36
|
+
* abandoned; the caller must still lower the layer's capture overlay on a `last` event.
|
|
37
|
+
*/
|
|
38
|
+
export function gestureAbandoned(first: boolean, memo: unknown): boolean {
|
|
39
|
+
return !first && memo === undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
28
42
|
/**
|
|
29
43
|
* Pointer displacement since the gesture started, corrected for layer scale.
|
|
30
44
|
*
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { useDrag } from "@use-gesture/react";
|
|
7
7
|
import { applyResize, clampRect, type Rect, type ResizeHandle } from "./window-geometry";
|
|
8
8
|
import {
|
|
9
|
+
gestureAbandoned,
|
|
9
10
|
gestureDisplacement,
|
|
10
11
|
WINDOW_DRAG_CONFIG,
|
|
11
12
|
type WindowGestureContext,
|
|
@@ -14,6 +15,10 @@ import {
|
|
|
14
15
|
export function useWindowResize(ctx: WindowGestureContext) {
|
|
15
16
|
return useDrag(
|
|
16
17
|
({ args, xy, initial, first, last, memo }) => {
|
|
18
|
+
if (gestureAbandoned(first, memo)) {
|
|
19
|
+
if (last) ctx.onGestureActive(false);
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
17
22
|
const handle = args[0] as ResizeHandle;
|
|
18
23
|
const base: Rect = first ? { ...ctx.getRect() } : (memo as Rect);
|
|
19
24
|
if (first) ctx.onGestureActive(true);
|
|
@@ -8,8 +8,6 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import { lazy, type ComponentType, type LazyExoticComponent } from "react";
|
|
11
|
-
import { ExplorerSkinChrome } from "@/components/os-explorer/skins/explorer-skin-chrome";
|
|
12
|
-
import type { WindowChrome } from "./window-chrome-contract";
|
|
13
11
|
import type { WindowKind } from "./window-store-types";
|
|
14
12
|
|
|
15
13
|
export interface WindowContentProps {
|
|
@@ -23,22 +21,9 @@ export const WINDOW_CONTENT: Record<WindowKind, LazyExoticComponent<ComponentTyp
|
|
|
23
21
|
explorer: lazy(() => import("@/components/os-explorer/explorer-window-content")),
|
|
24
22
|
"team-member": lazy(() => import("@/components/chat/team-member-window-content")),
|
|
25
23
|
"system-monitor": lazy(() => import("@/components/system/system-monitor-window-content")),
|
|
24
|
+
"tab-host": lazy(() => import("./tab-host-window-content")),
|
|
26
25
|
};
|
|
27
26
|
|
|
28
|
-
/**
|
|
29
|
-
* Per-kind titlebar chrome. `FloatingWindow` renders `chrome` directly with no
|
|
30
|
-
* `<Suspense>` around it, so — unlike `WINDOW_CONTENT` — entries here must be plain,
|
|
31
|
-
* synchronously-renderable components, not `lazy()`.
|
|
32
|
-
*/
|
|
33
|
-
export const WINDOW_CHROME: Partial<Record<WindowKind, WindowChrome>> = {
|
|
34
|
-
explorer: ExplorerSkinChrome,
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
/** Chrome for a window kind, or `undefined` to fall back to `DefaultWindowChrome`. */
|
|
38
|
-
export function chromeFor(kind: WindowKind): WindowChrome | undefined {
|
|
39
|
-
return WINDOW_CHROME[kind];
|
|
40
|
-
}
|
|
41
|
-
|
|
42
27
|
/** Titlebar text for a window. Falls back to the kind's generic name. */
|
|
43
28
|
export function windowTitle(kind: WindowKind, payload?: Record<string, unknown>): string {
|
|
44
29
|
const explicit = payload?.title;
|
|
@@ -48,6 +33,9 @@ export function windowTitle(kind: WindowKind, payload?: Record<string, unknown>)
|
|
|
48
33
|
return typeof member === "string" && member ? `Session — ${member}` : "Team member";
|
|
49
34
|
}
|
|
50
35
|
if (kind === "system-monitor") return "System Monitor";
|
|
36
|
+
// A detached tab carries its title in the payload; the generic name only shows for a
|
|
37
|
+
// window whose tab has not been resolved yet (restore before the layout is loaded).
|
|
38
|
+
if (kind === "tab-host") return "Tab";
|
|
51
39
|
const path = payload?.path;
|
|
52
40
|
if (kind === "explorer" && typeof path === "string" && path) {
|
|
53
41
|
const segments = path.split(/[\\/]/).filter(Boolean);
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import { Suspense, useCallback, useLayoutEffect, useRef, useState } from "react";
|
|
14
14
|
import { useIsMobile } from "@/hooks/use-is-mobile";
|
|
15
15
|
import { FloatingWindow } from "./floating-window";
|
|
16
|
-
import {
|
|
16
|
+
import { WINDOW_CONTENT, windowTitle } from "./window-content-registry";
|
|
17
17
|
import { Z_BASE, MAX_WINDOWS } from "./window-geometry";
|
|
18
18
|
import { useWindowStore, windowsInRankOrder } from "./window-store";
|
|
19
19
|
|
|
@@ -72,7 +72,6 @@ function DesktopWindowLayer() {
|
|
|
72
72
|
focused={win.id === frontId}
|
|
73
73
|
getScale={getScale}
|
|
74
74
|
onGestureActive={setCapturing}
|
|
75
|
-
chrome={chromeFor(win.kind)}
|
|
76
75
|
>
|
|
77
76
|
<Suspense fallback={<div className="p-3 text-xs text-text-2">Loading…</div>}>
|
|
78
77
|
<Content id={win.id} payload={win.payload} />
|