@hienlh/ppm 0.18.9 → 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/group-protected-probe.ts +21 -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 +63 -42
- package/.spike/vite-restart.err +663 -0
- package/.spike/w.err +569 -94
- package/CHANGELOG.md +25 -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-CdH_h0vD.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-CY_454vd.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-CuOQrHIS.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/format-bytes-WVcFxJuT.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-Cehfgrzc.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-pVzBdkpl.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-vTeeJYVZ.js +1 -0
- 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-CR6VpTrX.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/resolve-theme-CRt_7wpd.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-BPYsJDsn.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-CGucu3fb.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-C-Rxv8JN.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/system/build-kill-request.ts +28 -1
- package/src/web/components/system/chart-scale.ts +3 -3
- package/src/web/components/system/kill-confirm-dialog.tsx +44 -28
- package/src/web/components/system/metric-chart-canvas.tsx +1 -2
- package/src/web/components/system/process-columns-grid.ts +39 -29
- package/src/web/components/system/process-group-row.tsx +31 -8
- package/src/web/components/system/process-row.tsx +6 -7
- package/src/web/components/system/process-table-model.ts +4 -22
- package/src/web/components/system/process-table-toolbar.tsx +12 -43
- package/src/web/components/system/process-table.tsx +22 -63
- package/src/web/components/system/sortable-header.tsx +33 -8
- package/src/web/components/system/system-monitor-body.tsx +1 -1
- package/src/web/components/system/use-column-widths.ts +91 -0
- package/src/web/components/system/use-process-kill.ts +100 -0
- 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/src/web/styles/globals.css +5 -3
- package/src/web/theme/builtin/aurora.ts +8 -5
- package/dist/web/assets/ai-resource-editor-DFCuNe-P.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-flMPLoKb.js +0 -15
- package/dist/web/assets/code-editor-C2VQbXzw.js +0 -10
- package/dist/web/assets/context-menu-Cq0u3SK9.js +0 -1
- package/dist/web/assets/database-viewer-BCZOTrPT.js +0 -1
- package/dist/web/assets/diff-viewer-BwfMN-nW.js +0 -4
- package/dist/web/assets/docx-preview-D3Sdh_aT.js +0 -12
- package/dist/web/assets/explorer-body-BKOMM566.js +0 -2
- package/dist/web/assets/explorer-window-content-Bbzijk8t.js +0 -1
- package/dist/web/assets/format-bytes-Dk7B73B7.js +0 -1
- package/dist/web/assets/git-log-panel-DcV7PhqW.js +0 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-D4hYLNJU.js +0 -1
- package/dist/web/assets/group-chat-tab-BVPYxjz-.js +0 -1
- package/dist/web/assets/image-preview-D-Ok10eZ.js +0 -1
- package/dist/web/assets/index-CerSxGdf.js +0 -52
- package/dist/web/assets/index-DRA_OpWY.css +0 -2
- package/dist/web/assets/info-3K5VOQVL-lRlrTlkb.js +0 -1
- package/dist/web/assets/keybindings-store-aIY40k2o.js +0 -1
- package/dist/web/assets/markdown-renderer-I89kyQhe.js +0 -1
- package/dist/web/assets/mobile-bottom-sheet-BUOJgiaZ.js +0 -1
- package/dist/web/assets/mobile-explorer-sheet-5Uj9ZMM9.js +0 -1
- package/dist/web/assets/notification-store-DJ-OtAG3.js +0 -1
- package/dist/web/assets/overview-panel-Cgi3UPY1.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-Di5xHFyT.js +0 -1
- package/dist/web/assets/pie-UPGHQEXC-SLS6i76l.js +0 -1
- package/dist/web/assets/process-table-DL6shbzt.js +0 -1
- package/dist/web/assets/radar-KQ55EAFF-JJ6O1Er_.js +0 -1
- package/dist/web/assets/resolve-theme-IdhSR-gx.js +0 -1
- package/dist/web/assets/settings-tab-jbiQwozX.js +0 -1
- package/dist/web/assets/sqlite-viewer-Bq9ZJA2y.js +0 -1
- package/dist/web/assets/system-monitor-body-CKEYWyN9.js +0 -2
- package/dist/web/assets/system-monitor-tab-WjhFFHyM.js +0 -1
- package/dist/web/assets/system-monitor-window-content-CMiISeoC.js +0 -1
- package/dist/web/assets/team-member-sheet-oY5EkH53.js +0 -2
- package/dist/web/assets/team-member-window-content-yCBeI_5X.js +0 -1
- package/dist/web/assets/terminal-tab-BxHtMR7h.js +0 -3
- package/dist/web/assets/tool-cards-BcGrk1zk.js +0 -8
- package/dist/web/assets/treemap-KZPCXAKY-Be3KNmns.js +0 -1
- package/dist/web/assets/use-open-team-member-DdrRXj-M.js +0 -1
- package/dist/web/assets/video-preview-DYAbbmd0.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/src/web/components/system/sparkline-canvas.tsx +0 -63
- /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/{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/{riscv-BbbBYJBo.js → riscv-8b3-Ye4X.js} +0 -0
- /package/dist/web/assets/{ron-BtVTWW4b.js → ron-DrmU1KHP.js} +0 -0
- /package/dist/web/assets/{rose-pine-hvkvQzvU.js → rose-pine-C_-E2tF1.js} +0 -0
- /package/dist/web/assets/{rose-pine-dawn-D7lwhUei.js → rose-pine-dawn-DEfhNlFH.js} +0 -0
- /package/dist/web/assets/{rose-pine-moon-CoHDmsIw.js → rose-pine-moon-BdvX3gdn.js} +0 -0
- /package/dist/web/assets/{rosmsg-CdaZFgI8.js → rosmsg-B6GhGpd5.js} +0 -0
- /package/dist/web/assets/{rust-Dy2qsphD.js → rust-DmC97M1-.js} +0 -0
- /package/dist/web/assets/{sass-Bz7NVxDb.js → sass-B0tJOHLM.js} +0 -0
- /package/dist/web/assets/{save-C4z1p51e.js → save-CtIGOjmx.js} +0 -0
- /package/dist/web/assets/{scala-sXSwsNyq.js → scala-n8zaFOXv.js} +0 -0
- /package/dist/web/assets/{scheme-DS7TUbN7.js → scheme-BKD9ztBU.js} +0 -0
- /package/dist/web/assets/{sdbl-iISFvIep.js → sdbl-D8gB5-rS.js} +0 -0
- /package/dist/web/assets/{shellscript-BkIl4ApC.js → shellscript-BfXlf_Ao.js} +0 -0
- /package/dist/web/assets/{shield-check-C5laObJv.js → shield-check-B0iGUiOK.js} +0 -0
- /package/dist/web/assets/{shield-off-DULFtyLS.js → shield-off-BNLWBhcq.js} +0 -0
- /package/dist/web/assets/{slack-dark-B1eg0_m2.js → slack-dark-CylEddse.js} +0 -0
- /package/dist/web/assets/{slack-ochin-mdkc1ldu.js → slack-ochin-w8wg8vuC.js} +0 -0
- /package/dist/web/assets/{smalltalk-CORtd03t.js → smalltalk-hiAXA64u.js} +0 -0
- /package/dist/web/assets/{snazzy-light-Bc6Q2G89.js → snazzy-light-BwlV3Xty.js} +0 -0
- /package/dist/web/assets/{solarized-dark-CF83zRXM.js → solarized-dark-vmNGdykz.js} +0 -0
- /package/dist/web/assets/{solarized-light-BoKQZaYU.js → solarized-light-DGv_0JXq.js} +0 -0
- /package/dist/web/assets/{solidity-DOgi1N4w.js → solidity-Y7QSH0B1.js} +0 -0
- /package/dist/web/assets/{sparkles-Dqsf3hq6.js → sparkles-Dh-_J2Rd.js} +0 -0
- /package/dist/web/assets/{splunk-BXfw5ZLy.js → splunk-BtgpLjHi.js} +0 -0
- /package/dist/web/assets/{sql-BcVs-eX4.js → sql-CRHYhOia.js} +0 -0
- /package/dist/web/assets/{ssh-config-CLCtNkkd.js → ssh-config-DOqSs3au.js} +0 -0
- /package/dist/web/assets/{stylus-DdP992aO.js → stylus-crCAEaBT.js} +0 -0
- /package/dist/web/assets/{swift-BnGb6Lgc.js → swift-eE3rT7TC.js} +0 -0
- /package/dist/web/assets/{synthwave-84-cg9264l9.js → synthwave-84-BWy14LBX.js} +0 -0
- /package/dist/web/assets/{system-verilog-GbHpszs3.js → system-verilog-DC0-DZM4.js} +0 -0
- /package/dist/web/assets/{systemd-Dz-bNsDQ.js → systemd-to5p6N8I.js} +0 -0
- /package/dist/web/assets/{table-CHmxuh6M.js → table-Bbc783ko.js} +0 -0
- /package/dist/web/assets/{talonscript-CFIidoBA.js → talonscript-DoTcU8wm.js} +0 -0
- /package/dist/web/assets/{tasl-Cu-TRTKx.js → tasl-cNZvUs95.js} +0 -0
- /package/dist/web/assets/{tcl-DwCHCB1K.js → tcl-mZE8sZH8.js} +0 -0
- /package/dist/web/assets/{terraform-BzZw4T1z.js → terraform-CqHPpIfu.js} +0 -0
- /package/dist/web/assets/{tokyo-night-RKsj2-tv.js → tokyo-night-Tp2rTIZd.js} +0 -0
- /package/dist/web/assets/{toml-CirbOgDP.js → toml-CU_vscgn.js} +0 -0
- /package/dist/web/assets/{tsv-CraRcWdU.js → tsv-ik7iFB9D.js} +0 -0
- /package/dist/web/assets/{tsx-CjFg0lgw.js → tsx-BMvvMKiv.js} +0 -0
- /package/dist/web/assets/{turtle-B-WBIOa6.js → turtle-DBqKCq9o.js} +0 -0
- /package/dist/web/assets/{typescript-MpLarYn1.js → typescript-DXJDmMZZ.js} +0 -0
- /package/dist/web/assets/{typespec-B7QlHMZ_.js → typespec-CBseCMtZ.js} +0 -0
- /package/dist/web/assets/{typst-CcHSKFZj.js → typst-4oY25U9y.js} +0 -0
- /package/dist/web/assets/{use-is-mobile-BXGVvczu.js → use-is-mobile-D1weanbj.js} +0 -0
- /package/dist/web/assets/{utils-DoY4yTP-.js → utils-BNRH507E.js} +0 -0
- /package/dist/web/assets/{v-xTGhWZuD.js → v-BXaZ_1oy.js} +0 -0
- /package/dist/web/assets/{vala-DwebjH3H.js → vala-BImWJE7z.js} +0 -0
- /package/dist/web/assets/{vb-BxJT2RAy.js → vb-CLfj2_sy.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-CU6zIYMB.js → vendor-xterm-_yyu5n32.js} +0 -0
- /package/dist/web/assets/{verilog-CvV6RHPD.js → verilog-BWa8Ed2b.js} +0 -0
- /package/dist/web/assets/{vesper-CY3qd7E_.js → vesper-BGj1cg6m.js} +0 -0
- /package/dist/web/assets/{vhdl-B9ZX-sUL.js → vhdl-mByK7mlx.js} +0 -0
- /package/dist/web/assets/{viml-Y42h_ExQ.js → viml-CugmlW5g.js} +0 -0
- /package/dist/web/assets/{vitesse-black-DkXP6Sv-.js → vitesse-black-vPdpy9TL.js} +0 -0
- /package/dist/web/assets/{vitesse-dark-B9CkIB6r.js → vitesse-dark-BuQK3dUh.js} +0 -0
- /package/dist/web/assets/{vitesse-light-C7DHrJCK.js → vitesse-light-B3nz1XL9.js} +0 -0
- /package/dist/web/assets/{vyper-Cnd9s5j-.js → vyper-DH_GTIHG.js} +0 -0
- /package/dist/web/assets/{wasm-DQE71XTB.js → wasm-C-LF9GjX.js} +0 -0
- /package/dist/web/assets/{wasm-iWe7Fzjc.js → wasm-DfVbVJlW.js} +0 -0
- /package/dist/web/assets/{wenyan-Bc5Pnm9l.js → wenyan-CzQkHyHx.js} +0 -0
- /package/dist/web/assets/{wgsl-D-YUAWkP.js → wgsl-Du_M1DW9.js} +0 -0
- /package/dist/web/assets/{wikitext-DYQDUYf2.js → wikitext-BWN_w5S7.js} +0 -0
- /package/dist/web/assets/{wit-P6u7mfwy.js → wit-BR13v5HD.js} +0 -0
- /package/dist/web/assets/{wolfram-6SXLUqao.js → wolfram-BoXxp_Xl.js} +0 -0
- /package/dist/web/assets/{x-BcqfTY_7.js → x-nhriOX9o.js} +0 -0
- /package/dist/web/assets/{yaml-CQiMLVcZ.js → yaml-DpR_EF-d.js} +0 -0
- /package/dist/web/assets/{zenscript-DFMywo_P.js → zenscript-C-EdUtUd.js} +0 -0
- /package/dist/web/assets/{zig-CtAjaIiF.js → zig-BD4eA5nU.js} +0 -0
|
@@ -1,45 +1,50 @@
|
|
|
1
1
|
/** Pure grid-template builder for the process table. No React, so the visibility
|
|
2
|
-
* rules (which optional columns exist, which one survives below `@lg`)
|
|
3
|
-
* unit-testable without mounting a component.
|
|
2
|
+
* rules (which optional columns exist, which one survives below `@lg`) and the
|
|
3
|
+
* user-resized widths are unit-testable without mounting a component.
|
|
4
4
|
*
|
|
5
5
|
* Two responsive templates are computed up front and switched via CSS custom
|
|
6
6
|
* properties + a `@lg:` Tailwind class (see `PROCESS_ROW_GRID_CLASS` below) —
|
|
7
7
|
* Tailwind's arbitrary-value scan only needs the class NAME to be a static
|
|
8
|
-
* string; the var() value itself can vary at runtime.
|
|
9
|
-
* two-template approach the process table already used for the trend/age
|
|
10
|
-
* track, just parameterised by which optional columns the host can measure. */
|
|
8
|
+
* string; the var() value itself can vary at runtime. */
|
|
11
9
|
import type { CSSProperties } from "react";
|
|
12
10
|
import type { ProcessColumnAvailability, SortKey } from "../../../types/system-metrics";
|
|
13
11
|
|
|
14
12
|
export type OptionalColumnKey = "disk" | "gpu" | "net";
|
|
13
|
+
/** Every column whose width the user can drag. The name column takes the rest. */
|
|
14
|
+
export type ResizableColumnKey = "cpu" | "ram" | OptionalColumnKey;
|
|
15
15
|
|
|
16
16
|
/** Alias kept local so call sites don't need to know the exact server-contract
|
|
17
17
|
* type name — this module only cares about the three boolean flags. */
|
|
18
18
|
export type ProcessColumnsFlags = ProcessColumnAvailability;
|
|
19
19
|
|
|
20
|
+
/** px overrides from a drag; missing keys fall back to `DEFAULT_COLUMN_WIDTH`. */
|
|
21
|
+
export type ColumnWidths = Partial<Record<ResizableColumnKey, number>>;
|
|
22
|
+
|
|
20
23
|
const OPTIONAL_COLUMN_ORDER: OptionalColumnKey[] = ["disk", "gpu", "net"];
|
|
21
24
|
|
|
22
25
|
/** Disk/Net cells show two values ("↓ read ↑ write"); GPU shows one composite
|
|
23
26
|
* ("12% · 1.1 GB") and fits narrower. */
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
export const DEFAULT_COLUMN_WIDTH: Record<ResizableColumnKey, number> = {
|
|
28
|
+
cpu: 64,
|
|
29
|
+
ram: 80,
|
|
30
|
+
disk: 120,
|
|
31
|
+
gpu: 90,
|
|
32
|
+
net: 120,
|
|
28
33
|
};
|
|
34
|
+
/** Drag bounds: below 48px a "1.2 MB/s" no longer fits; above 400px the name
|
|
35
|
+
* column starves in a default-size window. */
|
|
36
|
+
export const MIN_COLUMN_WIDTH = 48;
|
|
37
|
+
export const MAX_COLUMN_WIDTH = 400;
|
|
29
38
|
|
|
30
|
-
|
|
31
|
-
* CPU, RAM at the start; the trend/age track (wide only) and the kill button at
|
|
32
|
-
* the end. */
|
|
33
|
-
const NAME_CPU_RAM = ["minmax(0,1fr)", "64px", "80px"];
|
|
34
|
-
const TREND_TRACK = "130px";
|
|
39
|
+
const NAME_TRACK = "minmax(0,1fr)";
|
|
35
40
|
const KILL_TRACK = "44px";
|
|
36
41
|
|
|
37
42
|
export interface ProcessGridResult {
|
|
38
43
|
/** Grid template for `@lg` and up: Name/CPU/RAM + every enabled optional column
|
|
39
|
-
* in a fixed order +
|
|
44
|
+
* in a fixed order + kill button. */
|
|
40
45
|
wideTemplate: string;
|
|
41
46
|
/** Grid template below `@lg`: Name/CPU/RAM + AT MOST the one optional column
|
|
42
|
-
* currently sorted by (if enabled) + kill button.
|
|
47
|
+
* currently sorted by (if enabled) + kill button. */
|
|
43
48
|
narrowTemplate: string;
|
|
44
49
|
/** Which optional columns are enabled at all (host can measure them). */
|
|
45
50
|
columns: ProcessColumnsFlags;
|
|
@@ -52,22 +57,27 @@ function isOptionalColumnKey(key: SortKey): key is OptionalColumnKey {
|
|
|
52
57
|
return key === "disk" || key === "gpu" || key === "net";
|
|
53
58
|
}
|
|
54
59
|
|
|
55
|
-
export function
|
|
60
|
+
export function clampColumnWidth(px: number): number {
|
|
61
|
+
return Math.round(Math.min(MAX_COLUMN_WIDTH, Math.max(MIN_COLUMN_WIDTH, px)));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function columnWidthPx(key: ResizableColumnKey, widths: ColumnWidths): number {
|
|
65
|
+
const w = widths[key];
|
|
66
|
+
return typeof w === "number" && Number.isFinite(w) ? clampColumnWidth(w) : DEFAULT_COLUMN_WIDTH[key];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function buildProcessGrid(
|
|
70
|
+
columns: ProcessColumnsFlags,
|
|
71
|
+
sortKey: SortKey,
|
|
72
|
+
widths: ColumnWidths = {},
|
|
73
|
+
): ProcessGridResult {
|
|
56
74
|
const enabled = OPTIONAL_COLUMN_ORDER.filter((k) => columns[k]);
|
|
57
75
|
const narrowExtra = isOptionalColumnKey(sortKey) && columns[sortKey] ? sortKey : null;
|
|
76
|
+
const track = (k: ResizableColumnKey) => `${columnWidthPx(k, widths)}px`;
|
|
77
|
+
const base = [NAME_TRACK, track("cpu"), track("ram")];
|
|
58
78
|
|
|
59
|
-
const wideTemplate = [
|
|
60
|
-
|
|
61
|
-
...enabled.map((k) => OPTIONAL_COLUMN_WIDTH[k]),
|
|
62
|
-
TREND_TRACK,
|
|
63
|
-
KILL_TRACK,
|
|
64
|
-
].join(" ");
|
|
65
|
-
|
|
66
|
-
const narrowTemplate = [
|
|
67
|
-
...NAME_CPU_RAM,
|
|
68
|
-
...(narrowExtra ? [OPTIONAL_COLUMN_WIDTH[narrowExtra]] : []),
|
|
69
|
-
KILL_TRACK,
|
|
70
|
-
].join(" ");
|
|
79
|
+
const wideTemplate = [...base, ...enabled.map(track), KILL_TRACK].join(" ");
|
|
80
|
+
const narrowTemplate = [...base, ...(narrowExtra ? [track(narrowExtra)] : []), KILL_TRACK].join(" ");
|
|
71
81
|
|
|
72
82
|
return { wideTemplate, narrowTemplate, columns, narrowExtra };
|
|
73
83
|
}
|
|
@@ -1,25 +1,28 @@
|
|
|
1
|
-
import { ChevronRight, ChevronDown } from "lucide-react";
|
|
1
|
+
import { ChevronRight, ChevronDown, X } from "lucide-react";
|
|
2
2
|
import { cn } from "@/lib/utils";
|
|
3
3
|
import { formatRam } from "@/lib/format-bytes";
|
|
4
4
|
import { cpuColor, formatDiskCell, formatGpuCell, formatNetCell, sumOptionalBps } from "./process-row-format";
|
|
5
5
|
import { optionalCellClassName, type ProcessGridResult } from "./process-columns-grid";
|
|
6
|
-
import { SparklineCanvas } from "./sparkline-canvas";
|
|
7
6
|
import type { ProcessGroup } from "../../../types/system-metrics";
|
|
8
7
|
|
|
8
|
+
const PROTECTED_GROUP_TOOLTIP = "Protected: this app contains a PPM or OS-critical process — cannot be ended as a whole.";
|
|
9
|
+
|
|
9
10
|
export interface ProcessGroupRowProps {
|
|
10
11
|
group: ProcessGroup;
|
|
11
12
|
expanded: boolean;
|
|
12
|
-
spark: number[];
|
|
13
13
|
grid: ProcessGridResult;
|
|
14
|
+
/** True when any member is refused by the kill guard — the whole-app button is disabled. */
|
|
15
|
+
killProtected: boolean;
|
|
14
16
|
onToggle: (key: string) => void;
|
|
17
|
+
onKillClick: (group: ProcessGroup) => void;
|
|
15
18
|
}
|
|
16
19
|
|
|
17
|
-
export function ProcessGroupRow({ group, expanded,
|
|
20
|
+
export function ProcessGroupRow({ group, expanded, grid, killProtected, onToggle, onKillClick }: ProcessGroupRowProps) {
|
|
18
21
|
const Chevron = expanded ? ChevronDown : ChevronRight;
|
|
19
22
|
|
|
20
23
|
return (
|
|
21
24
|
<div
|
|
22
|
-
className="grid items-center gap-1 min-h-11 md:min-h-7 px-3 text-xs cursor-pointer hover:bg-surface-hover transition-colors grid-cols-[var(--sysmon-grid-n)] @lg:grid-cols-[var(--sysmon-grid-w)]"
|
|
25
|
+
className="grid items-center gap-1 min-h-11 md:min-h-7 px-3 text-xs cursor-pointer hover:bg-surface-hover transition-colors group/proc grid-cols-[var(--sysmon-grid-n)] @lg:grid-cols-[var(--sysmon-grid-w)]"
|
|
23
26
|
onClick={() => onToggle(group.key)}
|
|
24
27
|
data-testid="sysmon-group-row"
|
|
25
28
|
data-group-key={group.key}
|
|
@@ -62,10 +65,30 @@ export function ProcessGroupRow({ group, expanded, spark, grid, onToggle }: Proc
|
|
|
62
65
|
{formatNetCell(group.netInBps, group.netOutBps)}
|
|
63
66
|
</span>
|
|
64
67
|
)}
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
{/* Same 44px track as the leaf rows' kill button, so ending a whole app (Notion
|
|
69
|
+
and its 7 helpers) is one click instead of seven. */}
|
|
70
|
+
<div className="flex justify-end">
|
|
71
|
+
<button
|
|
72
|
+
type="button"
|
|
73
|
+
onClick={(e) => {
|
|
74
|
+
e.stopPropagation();
|
|
75
|
+
onKillClick(group);
|
|
76
|
+
}}
|
|
77
|
+
disabled={killProtected}
|
|
78
|
+
aria-label={`End ${group.label} and its ${group.count} processes`}
|
|
79
|
+
title={killProtected ? PROTECTED_GROUP_TOOLTIP : `End ${group.label} (${group.count} processes)`}
|
|
80
|
+
data-testid="sysmon-group-kill-btn"
|
|
81
|
+
className={cn(
|
|
82
|
+
"flex items-center justify-center size-11 md:size-7 rounded transition-all",
|
|
83
|
+
"can-hover:opacity-0 can-hover:group-hover/proc:opacity-100",
|
|
84
|
+
killProtected
|
|
85
|
+
? "opacity-40 cursor-not-allowed"
|
|
86
|
+
: "hover:bg-error/20 hover:text-error active:bg-error/30",
|
|
87
|
+
)}
|
|
88
|
+
>
|
|
89
|
+
<X className="size-3.5" />
|
|
90
|
+
</button>
|
|
67
91
|
</div>
|
|
68
|
-
<div className="hidden @lg:block" />
|
|
69
92
|
</div>
|
|
70
93
|
);
|
|
71
94
|
}
|
|
@@ -26,9 +26,14 @@ export function ProcessRow({ proc, indent, grid, onKillClick }: ProcessRowProps)
|
|
|
26
26
|
data-gpu-pct={proc.gpuPct}
|
|
27
27
|
data-net-bps={sumOptionalBps(proc.netInBps, proc.netOutBps)}
|
|
28
28
|
>
|
|
29
|
+
{/* Uptime lives in the tooltip: a dedicated column cost 130px for a figure
|
|
30
|
+
that matters only when you are already looking at one row. */}
|
|
29
31
|
<div className={cn("flex items-start gap-1.5 min-w-0", indent && "pl-6")}>
|
|
30
32
|
<span className="text-text-subtle shrink-0">{proc.pid}</span>
|
|
31
|
-
<span
|
|
33
|
+
<span
|
|
34
|
+
className="truncate text-text-secondary"
|
|
35
|
+
title={proc.startedAt ? `${proc.command}\nRunning ${formatAge(proc.startedAt)}` : proc.command}
|
|
36
|
+
>
|
|
32
37
|
{proc.command}
|
|
33
38
|
</span>
|
|
34
39
|
</div>
|
|
@@ -49,12 +54,6 @@ export function ProcessRow({ proc, indent, grid, onKillClick }: ProcessRowProps)
|
|
|
49
54
|
{formatNetCell(proc.netInBps, proc.netOutBps)}
|
|
50
55
|
</span>
|
|
51
56
|
)}
|
|
52
|
-
<span
|
|
53
|
-
className="hidden @lg:block text-text-subtle text-right"
|
|
54
|
-
title={proc.startedAt ? new Date(proc.startedAt).toLocaleString() : ""}
|
|
55
|
-
>
|
|
56
|
-
{formatAge(proc.startedAt || undefined)}
|
|
57
|
-
</span>
|
|
58
57
|
<div className="flex justify-end">
|
|
59
58
|
<button
|
|
60
59
|
type="button"
|
|
@@ -2,26 +2,19 @@
|
|
|
2
2
|
* filter/sort/expand/rollup rules are unit-testable without mounting a component.
|
|
3
3
|
* Sort comparator lives in `process-table-sort.ts`, totals accumulator in
|
|
4
4
|
* `process-table-totals.ts` — both split out to stay under the file-size guideline. */
|
|
5
|
-
import type {
|
|
6
|
-
MetricsHistoryPoint,
|
|
7
|
-
ProcessGroup,
|
|
8
|
-
ProcessInfo,
|
|
9
|
-
SortDir,
|
|
10
|
-
SortKey,
|
|
11
|
-
} from "../../../types/system-metrics";
|
|
5
|
+
import type { ProcessGroup, ProcessInfo, SortDir, SortKey } from "../../../types/system-metrics";
|
|
12
6
|
import { sortByKey, sortFields } from "./process-table-sort";
|
|
13
7
|
import { accumulateTotals, EMPTY_TOTALS, type Totals } from "./process-table-totals";
|
|
14
8
|
|
|
15
9
|
export type { Totals } from "./process-table-totals";
|
|
16
10
|
|
|
17
11
|
export type TableRow =
|
|
18
|
-
| { kind: "group"; group: ProcessGroup; expanded: boolean
|
|
12
|
+
| { kind: "group"; group: ProcessGroup; expanded: boolean }
|
|
19
13
|
| { kind: "process"; proc: ProcessInfo; indent: boolean };
|
|
20
14
|
|
|
21
15
|
export interface BuildRowsInput {
|
|
22
16
|
processes: ProcessInfo[];
|
|
23
17
|
groups: ProcessGroup[];
|
|
24
|
-
history: MetricsHistoryPoint[];
|
|
25
18
|
mode: "grouped" | "flat";
|
|
26
19
|
ppmOnly: boolean;
|
|
27
20
|
query: string;
|
|
@@ -37,8 +30,6 @@ export interface BuildRowsResult {
|
|
|
37
30
|
autoExpanded: Set<string>;
|
|
38
31
|
}
|
|
39
32
|
|
|
40
|
-
const SPARK_POINTS = 60;
|
|
41
|
-
|
|
42
33
|
function matches(text: string, query: string): boolean {
|
|
43
34
|
return text.toLowerCase().includes(query);
|
|
44
35
|
}
|
|
@@ -47,13 +38,9 @@ function processMatches(proc: ProcessInfo, query: string): boolean {
|
|
|
47
38
|
return matches(proc.name, query) || matches(proc.command, query);
|
|
48
39
|
}
|
|
49
40
|
|
|
50
|
-
function sparkFor(history: MetricsHistoryPoint[], groupKey: string): number[] {
|
|
51
|
-
return history.slice(-SPARK_POINTS).map((h) => h.groups[groupKey]?.cpu ?? 0);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
41
|
/** Order fixed: filter (ppmOnly) -> filter (query) -> sort -> flatten (expand). */
|
|
55
42
|
export function buildRows(input: BuildRowsInput): BuildRowsResult {
|
|
56
|
-
const { processes, groups,
|
|
43
|
+
const { processes, groups, mode, ppmOnly, query, sortKey, sortDir, expanded } = input;
|
|
57
44
|
const q = query.trim().toLowerCase();
|
|
58
45
|
const byPid = new Map(processes.map((p) => [p.pid, p]));
|
|
59
46
|
|
|
@@ -93,12 +80,7 @@ export function buildRows(input: BuildRowsInput): BuildRowsResult {
|
|
|
93
80
|
const rows: TableRow[] = [];
|
|
94
81
|
for (const group of filteredGroups) {
|
|
95
82
|
const isExpanded = q ? autoExpanded.has(group.key) || expanded.has(group.key) : expanded.has(group.key);
|
|
96
|
-
rows.push({
|
|
97
|
-
kind: "group",
|
|
98
|
-
group,
|
|
99
|
-
expanded: isExpanded,
|
|
100
|
-
spark: sparkFor(history, group.key),
|
|
101
|
-
});
|
|
83
|
+
rows.push({ kind: "group", group, expanded: isExpanded });
|
|
102
84
|
if (!isExpanded) continue;
|
|
103
85
|
|
|
104
86
|
// Skip pids the current snapshot no longer has — a process can exit between the
|
|
@@ -5,7 +5,7 @@ import { formatRam } from "@/lib/format-bytes";
|
|
|
5
5
|
import { cpuColor, formatDiskCell, formatGpuCell, formatNetCell } from "./process-row-format";
|
|
6
6
|
import { optionalCellClassName, PROCESS_ROW_GRID_CLASS, type ProcessGridResult } from "./process-columns-grid";
|
|
7
7
|
import type { Totals } from "./process-table-totals";
|
|
8
|
-
import { SortableHeader } from "./sortable-header";
|
|
8
|
+
import { SortableHeader, type ColumnResizeHandlers } from "./sortable-header";
|
|
9
9
|
import type { SortDir, SortKey } from "../../../types/system-metrics";
|
|
10
10
|
|
|
11
11
|
const SEARCH_DEBOUNCE_MS = 150;
|
|
@@ -83,12 +83,15 @@ export interface ProcessTableHeaderProps {
|
|
|
83
83
|
sortDir: SortDir;
|
|
84
84
|
grid: ProcessGridResult;
|
|
85
85
|
onSort: (field: Exclude<SortKey, null>) => void;
|
|
86
|
+
resize: ColumnResizeHandlers;
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
/** Sticky column header row, grid-aligned with the rows below it. Disk/GPU/Net
|
|
89
90
|
* headers only render when the host reported that column as measurable
|
|
90
|
-
* (`grid.columns.<x>`); below `@lg` only the one currently sorted survives.
|
|
91
|
-
|
|
91
|
+
* (`grid.columns.<x>`); below `@lg` only the one currently sorted survives. Every
|
|
92
|
+
* fixed-width column carries a drag handle on its right edge. */
|
|
93
|
+
export function ProcessTableHeader({ sortKey, sortDir, grid, onSort, resize }: ProcessTableHeaderProps) {
|
|
94
|
+
const common = { activeKey: sortKey, activeDir: sortDir, onClick: onSort, resize };
|
|
92
95
|
return (
|
|
93
96
|
<div
|
|
94
97
|
role="row"
|
|
@@ -97,51 +100,18 @@ export function ProcessTableHeader({ sortKey, sortDir, grid, onSort }: ProcessTa
|
|
|
97
100
|
PROCESS_ROW_GRID_CLASS,
|
|
98
101
|
)}
|
|
99
102
|
>
|
|
100
|
-
<SortableHeader
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
activeKey={sortKey}
|
|
104
|
-
activeDir={sortDir}
|
|
105
|
-
onClick={onSort}
|
|
106
|
-
align="left"
|
|
107
|
-
testId="sysmon-sort-name"
|
|
108
|
-
/>
|
|
109
|
-
<SortableHeader label="CPU" field="cpu" activeKey={sortKey} activeDir={sortDir} onClick={onSort} testId="sysmon-sort-cpu" />
|
|
110
|
-
<SortableHeader label="RAM" field="ram" activeKey={sortKey} activeDir={sortDir} onClick={onSort} testId="sysmon-sort-ram" />
|
|
103
|
+
<SortableHeader label="Process" field="name" {...common} resize={undefined} align="left" testId="sysmon-sort-name" />
|
|
104
|
+
<SortableHeader label="CPU" field="cpu" {...common} resizeKey="cpu" testId="sysmon-sort-cpu" />
|
|
105
|
+
<SortableHeader label="RAM" field="ram" {...common} resizeKey="ram" testId="sysmon-sort-ram" />
|
|
111
106
|
{grid.columns.disk && (
|
|
112
|
-
<SortableHeader
|
|
113
|
-
label="Disk"
|
|
114
|
-
field="disk"
|
|
115
|
-
activeKey={sortKey}
|
|
116
|
-
activeDir={sortDir}
|
|
117
|
-
onClick={onSort}
|
|
118
|
-
testId="sysmon-col-disk"
|
|
119
|
-
className={optionalCellClassName(grid, "disk")}
|
|
120
|
-
/>
|
|
107
|
+
<SortableHeader label="Disk" field="disk" {...common} resizeKey="disk" testId="sysmon-col-disk" className={optionalCellClassName(grid, "disk")} />
|
|
121
108
|
)}
|
|
122
109
|
{grid.columns.gpu && (
|
|
123
|
-
<SortableHeader
|
|
124
|
-
label="GPU"
|
|
125
|
-
field="gpu"
|
|
126
|
-
activeKey={sortKey}
|
|
127
|
-
activeDir={sortDir}
|
|
128
|
-
onClick={onSort}
|
|
129
|
-
testId="sysmon-col-gpu"
|
|
130
|
-
className={optionalCellClassName(grid, "gpu")}
|
|
131
|
-
/>
|
|
110
|
+
<SortableHeader label="GPU" field="gpu" {...common} resizeKey="gpu" testId="sysmon-col-gpu" className={optionalCellClassName(grid, "gpu")} />
|
|
132
111
|
)}
|
|
133
112
|
{grid.columns.net && (
|
|
134
|
-
<SortableHeader
|
|
135
|
-
label="Net"
|
|
136
|
-
field="net"
|
|
137
|
-
activeKey={sortKey}
|
|
138
|
-
activeDir={sortDir}
|
|
139
|
-
onClick={onSort}
|
|
140
|
-
testId="sysmon-col-net"
|
|
141
|
-
className={optionalCellClassName(grid, "net")}
|
|
142
|
-
/>
|
|
113
|
+
<SortableHeader label="Net" field="net" {...common} resizeKey="net" testId="sysmon-col-net" className={optionalCellClassName(grid, "net")} />
|
|
143
114
|
)}
|
|
144
|
-
<span className="text-right hidden @lg:block">Trend</span>
|
|
145
115
|
<span />
|
|
146
116
|
</div>
|
|
147
117
|
);
|
|
@@ -183,7 +153,6 @@ export function ProcessTableFooter({ totals, grid, gpuUtilPercent }: ProcessTabl
|
|
|
183
153
|
{formatNetCell(totals.netInBps, totals.netOutBps)}
|
|
184
154
|
</span>
|
|
185
155
|
)}
|
|
186
|
-
<span className="hidden @lg:block" />
|
|
187
156
|
<span />
|
|
188
157
|
</div>
|
|
189
158
|
);
|
|
@@ -1,24 +1,15 @@
|
|
|
1
1
|
import { useCallback, useMemo, useRef, useState } from "react";
|
|
2
2
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
3
|
-
import { toast } from "sonner";
|
|
4
|
-
import { getAuthToken } from "@/lib/api-client";
|
|
5
3
|
import { useIsMobile } from "@/hooks/use-is-mobile";
|
|
6
4
|
import { buildRows, toggleSort } from "./process-table-model";
|
|
7
|
-
import { buildKillRequest } from "./build-kill-request";
|
|
8
5
|
import { buildProcessGrid, gridCssVars } from "./process-columns-grid";
|
|
9
6
|
import { ProcessTableToolbar, ProcessTableHeader, ProcessTableFooter } from "./process-table-toolbar";
|
|
10
7
|
import { ProcessGroupRow } from "./process-group-row";
|
|
11
8
|
import { ProcessRow } from "./process-row";
|
|
12
9
|
import { KillConfirmDialog } from "./kill-confirm-dialog";
|
|
13
|
-
import
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
MetricsHistoryPoint,
|
|
17
|
-
MetricsSnapshot,
|
|
18
|
-
ProcessInfo,
|
|
19
|
-
SortDir,
|
|
20
|
-
SortKey,
|
|
21
|
-
} from "../../../types/system-metrics";
|
|
10
|
+
import { useProcessKill } from "./use-process-kill";
|
|
11
|
+
import { useColumnWidths } from "./use-column-widths";
|
|
12
|
+
import type { MetricsSnapshot, SortDir, SortKey } from "../../../types/system-metrics";
|
|
22
13
|
|
|
23
14
|
/** Older cached bundles/snapshots (mid-rollout) predate `processColumns` — default
|
|
24
15
|
* every optional column off rather than let a missing field throw. */
|
|
@@ -26,39 +17,9 @@ const NO_OPTIONAL_COLUMNS = { disk: false, gpu: false, net: false };
|
|
|
26
17
|
|
|
27
18
|
export interface ProcessTableProps {
|
|
28
19
|
snapshot: MetricsSnapshot;
|
|
29
|
-
history: MetricsHistoryPoint[];
|
|
30
20
|
}
|
|
31
21
|
|
|
32
|
-
|
|
33
|
-
* kill route requires `X-PPM-Request: 1` — CSRF hardening, since a cross-origin HTML
|
|
34
|
-
* form cannot set a custom header, so a preflight becomes mandatory. A raw fetch here
|
|
35
|
-
* mirrors `handleResponse`'s single-Error-on-any-failure contract exactly, so the
|
|
36
|
-
* caller still has exactly one catch path. */
|
|
37
|
-
async function killProcess(request: KillProcessRequest): Promise<KillProcessResult> {
|
|
38
|
-
const token = getAuthToken();
|
|
39
|
-
const headers: Record<string, string> = {
|
|
40
|
-
"Content-Type": "application/json",
|
|
41
|
-
"X-PPM-Request": "1",
|
|
42
|
-
};
|
|
43
|
-
if (token) headers.Authorization = `Bearer ${token}`;
|
|
44
|
-
|
|
45
|
-
const res = await fetch("/api/system/resources/kill", {
|
|
46
|
-
method: "POST",
|
|
47
|
-
headers,
|
|
48
|
-
body: JSON.stringify(request),
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
let json: { ok: boolean; data?: KillProcessResult; error?: string };
|
|
52
|
-
try {
|
|
53
|
-
json = await res.json();
|
|
54
|
-
} catch {
|
|
55
|
-
throw new Error(res.ok ? "Empty response from server" : `Server error (HTTP ${res.status})`);
|
|
56
|
-
}
|
|
57
|
-
if (json.ok === false) throw new Error(json.error ?? `HTTP ${res.status}`);
|
|
58
|
-
return json.data as KillProcessResult;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
export function ProcessTable({ snapshot, history }: ProcessTableProps) {
|
|
22
|
+
export function ProcessTable({ snapshot }: ProcessTableProps) {
|
|
62
23
|
const isMobile = useIsMobile();
|
|
63
24
|
const parentRef = useRef<HTMLDivElement>(null);
|
|
64
25
|
|
|
@@ -68,14 +29,15 @@ export function ProcessTable({ snapshot, history }: ProcessTableProps) {
|
|
|
68
29
|
const [sortKey, setSortKey] = useState<SortKey>(null);
|
|
69
30
|
const [sortDir, setSortDir] = useState<SortDir>("desc");
|
|
70
31
|
const [expanded, setExpanded] = useState<Set<string>>(() => new Set());
|
|
71
|
-
const
|
|
32
|
+
const { pendingKill, groupProtected, requestKillProcess, requestKillGroup, confirmKill, cancelKill } =
|
|
33
|
+
useProcessKill(snapshot);
|
|
34
|
+
const { widths, begin: onResizeStart, reset: onResizeReset } = useColumnWidths();
|
|
72
35
|
|
|
73
36
|
const { rows, totals } = useMemo(
|
|
74
37
|
() =>
|
|
75
38
|
buildRows({
|
|
76
39
|
processes: snapshot.processes,
|
|
77
40
|
groups: snapshot.groups,
|
|
78
|
-
history,
|
|
79
41
|
mode,
|
|
80
42
|
ppmOnly,
|
|
81
43
|
query,
|
|
@@ -83,11 +45,11 @@ export function ProcessTable({ snapshot, history }: ProcessTableProps) {
|
|
|
83
45
|
sortDir,
|
|
84
46
|
expanded,
|
|
85
47
|
}),
|
|
86
|
-
[snapshot.processes, snapshot.groups,
|
|
48
|
+
[snapshot.processes, snapshot.groups, mode, ppmOnly, query, sortKey, sortDir, expanded],
|
|
87
49
|
);
|
|
88
50
|
|
|
89
51
|
const columns = snapshot.processColumns ?? NO_OPTIONAL_COLUMNS;
|
|
90
|
-
const grid = useMemo(() => buildProcessGrid(columns, sortKey), [columns, sortKey]);
|
|
52
|
+
const grid = useMemo(() => buildProcessGrid(columns, sortKey, widths), [columns, sortKey, widths]);
|
|
91
53
|
const gpuUtilPercent = snapshot.system.gpus[0]?.utilPercent;
|
|
92
54
|
|
|
93
55
|
const virtualizer = useVirtualizer({
|
|
@@ -115,16 +77,6 @@ export function ProcessTable({ snapshot, history }: ProcessTableProps) {
|
|
|
115
77
|
});
|
|
116
78
|
}, []);
|
|
117
79
|
|
|
118
|
-
const handleConfirmKill = useCallback(async (proc: ProcessInfo, tree: boolean) => {
|
|
119
|
-
setPendingKill(null);
|
|
120
|
-
try {
|
|
121
|
-
await killProcess(buildKillRequest(proc, tree));
|
|
122
|
-
toast.success(`Ended ${proc.name} (${proc.pid})`);
|
|
123
|
-
} catch (e) {
|
|
124
|
-
toast.error(e instanceof Error ? e.message : `Failed to end ${proc.name}`);
|
|
125
|
-
}
|
|
126
|
-
}, []);
|
|
127
|
-
|
|
128
80
|
// `@container`: the trend/age track is toggled on the table's own width, not the
|
|
129
81
|
// viewport — a floating window is routinely narrower than the screen it sits on.
|
|
130
82
|
// `gridCssVars` sets `--sysmon-grid-n`/`--sysmon-grid-w` once here; CSS custom
|
|
@@ -143,7 +95,13 @@ export function ProcessTable({ snapshot, history }: ProcessTableProps) {
|
|
|
143
95
|
onPpmOnlyChange={setPpmOnly}
|
|
144
96
|
onQueryChange={setQuery}
|
|
145
97
|
/>
|
|
146
|
-
<ProcessTableHeader
|
|
98
|
+
<ProcessTableHeader
|
|
99
|
+
sortKey={sortKey}
|
|
100
|
+
sortDir={sortDir}
|
|
101
|
+
grid={grid}
|
|
102
|
+
onSort={handleSort}
|
|
103
|
+
resize={{ onResizeStart, onResizeReset }}
|
|
104
|
+
/>
|
|
147
105
|
<div ref={parentRef} className="flex-1 min-h-0 overflow-y-auto">
|
|
148
106
|
<div style={{ height: virtualizer.getTotalSize(), position: "relative" }}>
|
|
149
107
|
{virtualizer.getVirtualItems().map((item) => {
|
|
@@ -164,12 +122,13 @@ export function ProcessTable({ snapshot, history }: ProcessTableProps) {
|
|
|
164
122
|
<ProcessGroupRow
|
|
165
123
|
group={row.group}
|
|
166
124
|
expanded={row.expanded}
|
|
167
|
-
spark={row.spark}
|
|
168
125
|
grid={grid}
|
|
126
|
+
killProtected={groupProtected.get(row.group.key) ?? true}
|
|
169
127
|
onToggle={handleToggleGroup}
|
|
128
|
+
onKillClick={requestKillGroup}
|
|
170
129
|
/>
|
|
171
130
|
) : (
|
|
172
|
-
<ProcessRow proc={row.proc} indent={row.indent} grid={grid} onKillClick={
|
|
131
|
+
<ProcessRow proc={row.proc} indent={row.indent} grid={grid} onKillClick={requestKillProcess} />
|
|
173
132
|
)}
|
|
174
133
|
</div>
|
|
175
134
|
);
|
|
@@ -178,9 +137,9 @@ export function ProcessTable({ snapshot, history }: ProcessTableProps) {
|
|
|
178
137
|
</div>
|
|
179
138
|
<ProcessTableFooter totals={totals} grid={grid} gpuUtilPercent={gpuUtilPercent} />
|
|
180
139
|
<KillConfirmDialog
|
|
181
|
-
|
|
182
|
-
onConfirm={
|
|
183
|
-
onCancel={
|
|
140
|
+
target={pendingKill}
|
|
141
|
+
onConfirm={confirmKill}
|
|
142
|
+
onCancel={cancelKill}
|
|
184
143
|
/>
|
|
185
144
|
</div>
|
|
186
145
|
);
|
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import { ArrowUp, ArrowDown } from "lucide-react";
|
|
2
2
|
import { cn } from "@/lib/utils";
|
|
3
3
|
import type { SortDir, SortKey } from "../../../types/system-metrics";
|
|
4
|
+
import type { ResizableColumnKey } from "./process-columns-grid";
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
export interface ColumnResizeHandlers {
|
|
7
|
+
onResizeStart: (key: ResizableColumnKey, e: { clientX: number; preventDefault: () => void }) => void;
|
|
8
|
+
onResizeReset: (key: ResizableColumnKey) => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Sortable column header shared by the process table toolbar. Renders as a
|
|
12
|
+
* `columnheader` `<div>`, not a `<th>` — the parent row is a CSS-grid
|
|
13
|
+
* `<div role="row">`, and a `<th>` inside a non-table ancestor both triggers React's
|
|
14
|
+
* DOM-nesting warning and makes `aria-sort` meaningless to assistive tech outside
|
|
15
|
+
* an actual table. */
|
|
10
16
|
export function SortableHeader({
|
|
11
17
|
label,
|
|
12
18
|
field,
|
|
@@ -16,6 +22,8 @@ export function SortableHeader({
|
|
|
16
22
|
align = "right",
|
|
17
23
|
testId,
|
|
18
24
|
className,
|
|
25
|
+
resizeKey,
|
|
26
|
+
resize,
|
|
19
27
|
}: {
|
|
20
28
|
label: string;
|
|
21
29
|
field: Exclude<SortKey, null>;
|
|
@@ -29,6 +37,9 @@ export function SortableHeader({
|
|
|
29
37
|
/** Extra classes on the outer `columnheader` — e.g. the `hidden @lg:block`
|
|
30
38
|
* visibility rule an optional (Disk/GPU/Net) column needs below `@lg`. */
|
|
31
39
|
className?: string;
|
|
40
|
+
/** Present for fixed-width columns: renders the drag handle on the right edge. */
|
|
41
|
+
resizeKey?: ResizableColumnKey;
|
|
42
|
+
resize?: ColumnResizeHandlers;
|
|
32
43
|
}) {
|
|
33
44
|
const isActive = activeKey === field;
|
|
34
45
|
const Arrow = isActive ? (activeDir === "asc" ? ArrowUp : ArrowDown) : null;
|
|
@@ -39,7 +50,7 @@ export function SortableHeader({
|
|
|
39
50
|
role="columnheader"
|
|
40
51
|
aria-sort={ariaSort}
|
|
41
52
|
className={cn(
|
|
42
|
-
"py-1.5 px-2 font-medium select-none",
|
|
53
|
+
"relative py-1.5 px-2 font-medium select-none",
|
|
43
54
|
align === "left" ? "text-left" : "text-right",
|
|
44
55
|
className,
|
|
45
56
|
)}
|
|
@@ -57,9 +68,23 @@ export function SortableHeader({
|
|
|
57
68
|
isActive && "text-text-primary",
|
|
58
69
|
)}
|
|
59
70
|
>
|
|
60
|
-
<span>{label}</span>
|
|
61
|
-
{Arrow && <Arrow className="size-3" />}
|
|
71
|
+
<span className="truncate">{label}</span>
|
|
72
|
+
{Arrow && <Arrow className="size-3 shrink-0" />}
|
|
62
73
|
</button>
|
|
74
|
+
{/* Drag handle: pointer-only (hidden below `md`, where the table is a
|
|
75
|
+
single narrow column set and there is nothing worth resizing). Double-click
|
|
76
|
+
returns the column to its default width. */}
|
|
77
|
+
{resizeKey && resize && (
|
|
78
|
+
<div
|
|
79
|
+
role="separator"
|
|
80
|
+
aria-orientation="vertical"
|
|
81
|
+
aria-label={`Resize ${label} column`}
|
|
82
|
+
data-testid={testId ? `${testId}-resize` : undefined}
|
|
83
|
+
onPointerDown={(e) => resize.onResizeStart(resizeKey, e)}
|
|
84
|
+
onDoubleClick={() => resize.onResizeReset(resizeKey)}
|
|
85
|
+
className="hidden md:block absolute top-0 -right-1 h-full w-2 cursor-col-resize hover:bg-primary/40 active:bg-primary/60"
|
|
86
|
+
/>
|
|
87
|
+
)}
|
|
63
88
|
</div>
|
|
64
89
|
);
|
|
65
90
|
}
|
|
@@ -137,7 +137,7 @@ export const SystemMonitorBody = memo(function SystemMonitorBody({
|
|
|
137
137
|
) : tab === "overview" ? (
|
|
138
138
|
<OverviewPanel system={latest.system} history={history} />
|
|
139
139
|
) : (
|
|
140
|
-
<ProcessTable snapshot={latest}
|
|
140
|
+
<ProcessTable snapshot={latest} />
|
|
141
141
|
)}
|
|
142
142
|
</Suspense>
|
|
143
143
|
</div>
|