collabmd 0.1.48 → 0.1.49
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/README.md +61 -5
- package/bin/collabmd.js +3 -0
- package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-C-nmgL5g.js +1 -0
- package/dist/client/assets/abnfDiagram-VCTEODGH-CdVZqicp.js +1 -0
- package/dist/client/assets/{architectureDiagram-5GKGNRK7-I39sYjHI.js → architectureDiagram-5GKGNRK7-wUo0bXif.js} +3 -3
- package/dist/client/assets/{blockDiagram-NRAW4CY4-C6DtJy5Y.js → blockDiagram-I7D4REHJ-BRSK3m49.js} +4 -4
- package/dist/client/assets/browser-utils-DbXSMI-6.js +1 -0
- package/dist/client/assets/{c4Diagram-UCG6FXSJ-CtWtxS9_.js → c4Diagram-7LVT6UL2-yD2poxqw.js} +1 -1
- package/dist/client/assets/channel-Fa4GS_-F.js +1 -0
- package/dist/client/assets/chunk-2E4U76K2-BPnTT-J3.js +2 -0
- package/dist/client/assets/{chunk-TEH6E4GO-DVayPj-q.js → chunk-4HAMMTFA-DStbIfJ1.js} +20 -20
- package/dist/client/assets/{chunk-75Z2AOVW-CdFSaPjz.js → chunk-75Z2AOVW-C5pGd3W9.js} +1 -1
- package/dist/client/assets/{chunk-CLGD4ZFX-DQLgbQrv.js → chunk-CLGD4ZFX-BMeArk03.js} +1 -1
- package/dist/client/assets/chunk-DU6HZSFF-Zkp69c6c.js +127 -0
- package/dist/client/assets/{chunk-F27PBJKO-CNHIFhjo.js → chunk-F27PBJKO-D4xNct1r.js} +1 -1
- package/dist/client/assets/{chunk-GMAD6QVW-CbcBqPM5.js → chunk-GMAD6QVW-NZ6WpDb8.js} +1 -1
- package/dist/client/assets/{chunk-OBVCFTLP-BJR7u1jh.js → chunk-GVQU2GXP-D8SDprfX.js} +1 -1
- package/dist/client/assets/{chunk-G27WJ6UU-D9-eg537.js → chunk-IMKFNOWR-D8jEuU3Q.js} +2 -2
- package/dist/client/assets/{chunk-JQ64N6SF-DSFNH4bh.js → chunk-L3NEJ4N5-aijKP-eh.js} +1 -1
- package/dist/client/assets/chunk-OSK3NFVY-CCbLQAMa.js +10 -0
- package/dist/client/assets/{chunk-P2QGCYS3-BRpqY32H.js → chunk-P2QGCYS3-Oag_FdCq.js} +1 -1
- package/dist/client/assets/{chunk-POPQ4Y6H-Cb4SlVZF.js → chunk-POPQ4Y6H-CYnpIgXT.js} +1 -1
- package/dist/client/assets/{chunk-PWAF6VOD-Cz8IwBB5.js → chunk-PWAF6VOD-JSNrcBmP.js} +1 -1
- package/dist/client/assets/{chunk-RM4UPSZO-CWRwxNWJ.js → chunk-RM4UPSZO-DOWllDY8.js} +4 -4
- package/dist/client/assets/{chunk-RHFEMEQ7-CWY8cf4H.js → chunk-SHT3W25Y-BiQGljao.js} +5 -5
- package/dist/client/assets/{chunk-SVP7TREG-CyHOmcac.js → chunk-SVP7TREG-DB485R5x.js} +1 -1
- package/dist/client/assets/{chunk-LCL6LL3I-DmDkVukh.js → chunk-TICWLB2K-8rAVvoS3.js} +4 -4
- package/dist/client/assets/{chunk-CKBBP62Z-DG26UiBv.js → chunk-TLUHSLCS-DTY5v0aj.js} +2 -2
- package/dist/client/assets/classDiagram-ZZMXUADV-BsQWoR3Q.js +1 -0
- package/dist/client/assets/classDiagram-v2-VYDZK3BY-BsQWoR3Q.js +1 -0
- package/dist/client/assets/{comment-thread-store-CdcwrObc.js → comment-thread-store-CX98zR6q.js} +1 -1
- package/dist/client/assets/comment-threads-BnRwo5B9.js +4 -0
- package/dist/client/assets/{cynefinDiagram-5FMLGOSQ-CdTPi2yO.js → cynefinDiagram-5FMLGOSQ-rTz9RhFH.js} +1 -1
- package/dist/client/assets/{dagre-3AP2YEHR-5gtJtd0O.js → dagre-GXQ25YYZ-Cr67wLpQ.js} +2 -2
- package/dist/client/assets/{diagram-S7CK7UJ4-BudWz9WU.js → diagram-S7CK7UJ4-DywERe__.js} +2 -2
- package/dist/client/assets/{diagram-UQ7AKVKN-3v4rbH-s.js → diagram-UQ7AKVKN-CNYlXtu4.js} +1 -1
- package/dist/client/assets/diagram-VSXAHHWV-0H1a61Bn.js +3 -0
- package/dist/client/assets/{diagram-VX7I27RA-C_-rj0sw.js → diagram-VX7I27RA-CsJbsx5F.js} +1 -1
- package/dist/client/assets/{diagram-Z3DM3KII-B4yxavgj.js → diagram-Z3DM3KII-D0mLxEgI.js} +1 -1
- package/dist/client/assets/dist--hk9I5HQ.js +1 -0
- package/dist/client/assets/{dist-DutPuFmC.js → dist-B1XEa-Zs.js} +1 -1
- package/dist/client/assets/dist-Bd1JucQF.js +1 -0
- package/dist/client/assets/{dist-DZAAWTG-.js → dist-C0G3AaXG.js} +1 -1
- package/dist/client/assets/dist-Dm4w5UId.js +1 -0
- package/dist/client/assets/{dist-B_yQaEv_.js → dist-DpYDHR9p.js} +1 -1
- package/dist/client/assets/{dist-CietwTVS.js → dist-DzNmC81X.js} +1 -1
- package/dist/client/assets/{dist-DDUn5zTz.js → dist-GvvCNBe4.js} +1 -1
- package/dist/client/assets/dist-JaU3aRlD.js +19 -0
- package/dist/client/assets/{dist-Bw3VIE_v.js → dist-TW8iFRyW.js} +1 -1
- package/dist/client/assets/{dist-Dir5dDKZ.js → dist-jVU5Be5P.js} +1 -1
- package/dist/client/assets/document-formatter-rDDjRfZ2.js +2 -0
- package/dist/client/assets/drawioEditor-JubEEha7.js +9 -0
- package/dist/client/assets/ebnfDiagram-PWID7BFC-HeTxHpCU.js +1 -0
- package/dist/client/assets/editor-session-Bk6oIvSr.js +54 -0
- package/dist/client/assets/{embedded-editor-base-B3l6Xy65.css → embedded-editor-base-BlCgz6mw.css} +1 -1
- package/dist/client/assets/{erDiagram-SSCWMZ5O-C-iy6VkX.js → erDiagram-RLTQ6QDP-CbrDdd5P.js} +2 -2
- package/dist/client/assets/{vault-utils-DvoSftJT.js → es-Bfdp096f.js} +13 -13
- package/dist/client/assets/excalidraw-element-link-YLIaTnVF.js +7 -0
- package/dist/client/assets/{excalidraw-scene-BOben2gr.js → excalidraw-scene-6uROebca.js} +1 -1
- package/dist/client/assets/excalidrawEditor-dBMbRX_S.js +9 -0
- package/dist/client/assets/export-page-CRRQ2NEl.js +57 -0
- package/dist/client/assets/exportDocument-BlQRd9_m.js +2 -0
- package/dist/client/assets/exportDocument-CNSbjZwu.css +1 -0
- package/dist/client/assets/flowDiagram-HODETNUW-D5Gy0wmg.js +1 -0
- package/dist/client/assets/{ganttDiagram-EL5Y4UJY-DtKHAbez.js → ganttDiagram-EL5Y4UJY-BHgOYiZz.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-WWUBYQGX-oue8fQ5o.js → gitGraphDiagram-WWUBYQGX-Dl__X3Sk.js} +1 -1
- package/dist/client/assets/image-ZVKINSPA-DgzW5zAy.js +1 -0
- package/dist/client/assets/index-D3RER1SZ.js +1023 -0
- package/dist/client/assets/index-DREVKl_K.css +1 -0
- package/dist/client/assets/{infoDiagram-RXCK75RN-BMzo6KIn.js → infoDiagram-27XIBGKW-DBpoANC9.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-5VMMS53U-BIM3h287.js → ishikawaDiagram-5VMMS53U-BMPC6hfp.js} +1 -1
- package/dist/client/assets/{journeyDiagram-EYS64GPL-mF6Lh8O-.js → journeyDiagram-3NMN7TZE-B1sApUmM.js} +2 -2
- package/dist/client/assets/{kanban-definition-3QL26DDD-DLN2NyoR.js → kanban-definition-UXKFOSKX-C9yP4td1.js} +4 -4
- package/dist/client/assets/{line-BfTWJmgf.js → line-BFl3ujec.js} +1 -1
- package/dist/client/assets/mermaid.core-BrY09czX.js +11 -0
- package/dist/client/assets/mermaid.core-DfcNfOTv.js +1 -0
- package/dist/client/assets/{mindmap-definition-FBJOCRG2-CRyHaHTk.js → mindmap-definition-YA3MSWOX-BUQHcYbK.js} +8 -8
- package/dist/client/assets/pegDiagram-XKGWAZYB-Bi2Iml7Z.js +1 -0
- package/dist/client/assets/{pieDiagram-E7YTZNPT-B5OZPb88.js → pieDiagram-E7YTZNPT-_gYXnMoi.js} +1 -1
- package/dist/client/assets/preview-render-compiler-CfxJYldJ.js +41 -0
- package/dist/client/assets/preview-render-compiler-Cu8_i9iS.js +1 -0
- package/dist/client/assets/{preview-render-worker-_QTxqKvP.js → preview-render-worker-c4Yi93qW.js} +41 -35
- package/dist/client/assets/prod-BiJL30sl.js +1 -0
- package/dist/client/assets/prod-qAk7rHa4.js +177 -0
- package/dist/client/assets/{quadrantDiagram-AXDQQJYC-Drrw14YH.js → quadrantDiagram-AXDQQJYC-DwexhEhd.js} +1 -1
- package/dist/client/assets/quick-switcher-controller-BoIK_wuG.js +1 -0
- package/dist/client/assets/railroadDiagram-O6MQD6OU-BVA5UbMu.js +1 -0
- package/dist/client/assets/{requirementDiagram-EFPCY7ZU-CRZG6mRB.js → requirementDiagram-BXWQKSXE-C4cKwiIw.js} +2 -2
- package/dist/client/assets/runtime-config-DcmnGcXU.js +1 -0
- package/dist/client/assets/{sankeyDiagram-P5KCCOFB-DvarEJpo.js → sankeyDiagram-P5KCCOFB-B5HHkRT2.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-WJ2MYXX4-B4oWlb-w.js → sequenceDiagram-WJ2MYXX4-BX6jqJFD.js} +6 -6
- package/dist/client/assets/{stateDiagram-HBIQ2CUA-qbHIIqRZ.js → stateDiagram-D77RDMKH-CmqxyRGx.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-MP3YSRHH-zoLLQVyh.js +1 -0
- package/dist/client/assets/{swimlanes-XN3QIQJK-xB6CtUGj.js → swimlanes-42K2YHIH-Bmgb9Zld.js} +1 -1
- package/dist/client/assets/swimlanesDiagram-VR7AAH4N-DS-KQN37.js +8 -0
- package/dist/client/assets/{timeline-definition-24CTP7MA-Lj_yTNlY.js → timeline-definition-24CTP7MA-BA-lVH6P.js} +1 -1
- package/dist/client/assets/vault-api-client-iZLhMJKe.js +6 -0
- package/dist/client/assets/{vennDiagram-4TSXK5OY-BekRp5Y0.js → vennDiagram-4TSXK5OY-DNdUC_Xj.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-VM6X3IG4-kdnV_Hdm.js → wardleyDiagram-VM6X3IG4-C2oY-YbF.js} +1 -1
- package/dist/client/assets/wiki-link-resolver-DFIwErjc.js +1 -0
- package/dist/client/assets/{xychartDiagram-S5SC5T6Z-DufGwNSB.js → xychartDiagram-S5SC5T6Z-CoIR8CBX.js} +1 -1
- package/dist/client/assets/{yjs-provider-reset-guard-DE0vINDP.js → yjs-provider-reset-guard-9ul1qF6k.js} +1 -1
- package/dist/client/drawio-editor.html +11 -3
- package/dist/client/excalidraw-editor.html +45 -2
- package/dist/client/export-document.html +3 -3
- package/dist/client/index.html +67 -35
- package/integrations/pi/index.ts +94 -0
- package/package.json +41 -32
- package/src/client/app/drawio-editor.html +2 -2
- package/src/client/app/excalidraw-editor.html +2 -2
- package/src/client/app/export-document.html +1 -1
- package/src/client/app/index.html +49 -33
- package/src/client/app/main-entry.js +15 -1
- package/src/client/application/app-shell/chat-feature.js +7 -22
- package/src/client/application/app-shell/git-feature.js +23 -5
- package/src/client/application/app-shell/presence-feature.js +8 -25
- package/src/client/application/app-shell/ui-feature-shell.js +36 -91
- package/src/client/application/app-shell/ui-feature-sidebar.js +43 -7
- package/src/client/application/app-shell/ui-feature-tab-activity.js +19 -6
- package/src/client/application/app-shell/ui-feature-toolbar.js +16 -129
- package/src/client/application/app-shell-elements.js +4 -0
- package/src/client/application/preview-render-compiler.js +1 -87
- package/src/client/application/preview-render-scheduler.js +8 -24
- package/src/client/application/preview-renderer.js +2 -2
- package/src/client/application/webmcp-diagram-renderer.js +47 -0
- package/src/client/application/workspace-coordinator.js +3 -1
- package/src/client/application/workspace-route-controller.js +7 -0
- package/src/client/bootstrap/collabmd-app-shell.js +78 -1
- package/src/client/domain/excalidraw-element-link.js +73 -0
- package/src/client/domain/excalidraw-scene.js +21 -0
- package/src/client/domain/hash-routes.js +8 -0
- package/src/client/domain/room.js +1 -5
- package/src/client/domain/runtime-paths.js +5 -0
- package/src/client/excalidraw-editor.js +135 -10
- package/src/client/export/export-host.js +3 -1
- package/src/client/export/export-pipeline.js +4 -17
- package/src/client/infrastructure/agent-connection-api-client.js +23 -0
- package/src/client/infrastructure/auth-client.js +3 -13
- package/src/client/infrastructure/editor-session.js +11 -0
- package/src/client/infrastructure/editor-view-adapter.js +13 -0
- package/src/client/infrastructure/excalidraw-room-client.js +80 -1
- package/src/client/infrastructure/git-api-client.js +39 -33
- package/src/client/infrastructure/lobby-presence.js +2 -5
- package/src/client/infrastructure/runtime-config.js +11 -1
- package/src/client/infrastructure/tab-activity-lock.js +2 -5
- package/src/client/infrastructure/vault-api-client.js +33 -26
- package/src/client/infrastructure/webmcp-tool-registry.js +283 -0
- package/src/client/infrastructure/workspace-sync-client.js +6 -4
- package/src/client/presentation/agent-connection-controller.js +255 -0
- package/src/client/presentation/backlinks-panel.js +3 -0
- package/src/client/presentation/bases-preview-controller.js +27 -18
- package/src/client/presentation/comment-ui/comment-ui-card.js +4 -2
- package/src/client/presentation/create-menu-presenter.js +19 -16
- package/src/client/presentation/excalidraw-embed-controller.js +164 -4
- package/src/client/presentation/file-explorer-view.js +70 -12
- package/src/client/presentation/file-history-view-controller.js +13 -11
- package/src/client/presentation/git-diff-view-controller.js +35 -43
- package/src/client/presentation/git-panel-controller.js +77 -27
- package/src/client/presentation/image-lightbox-controller.js +20 -16
- package/src/client/presentation/layout-controller.js +3 -1
- package/src/client/presentation/quick-switcher-controller.js +20 -78
- package/src/client/presentation/quick-switcher-text-search.js +10 -14
- package/src/client/styles/components/navigation.css +1 -2
- package/src/client/styles/features/agent-connection.css +202 -0
- package/src/client/styles/features/collaboration-chat.css +8 -1
- package/src/client/styles/features/collaboration-dialogs.css +16 -1
- package/src/client/styles/features/collaboration-presence.css +17 -4
- package/src/client/styles/features/diff-toolbar.css +1 -1
- package/src/client/styles/features/media-lightbox.css +12 -3
- package/src/client/styles/features/quick-switcher.css +20 -11
- package/src/client/styles/foundation/themes.css +2 -0
- package/src/client/styles/layout/editor-page.css +25 -11
- package/src/client/styles/layout/responsive.css +2 -20
- package/src/client/styles/layout/shell.css +1 -0
- package/src/client/styles/layout/sidebar.css +7 -4
- package/src/client/styles/primitives/controls.css +21 -54
- package/src/client/styles/style.css +1 -0
- package/src/domain/agent-tool-definitions.js +796 -0
- package/src/domain/collabmd-content-capabilities.js +149 -0
- package/src/domain/collaboration-protocol.js +2 -0
- package/src/domain/comment-threads.js +3 -5
- package/src/domain/diagram-source.js +50 -0
- package/src/domain/editable-content-revision.js +10 -0
- package/src/domain/editable-text.js +3 -0
- package/src/domain/exact-text-edits.js +69 -0
- package/src/domain/excalidraw-agent-scene.js +522 -0
- package/src/domain/excalidraw-agent-verification.js +460 -0
- package/src/domain/excalidraw-room-codec.js +1 -5
- package/src/domain/video-embed.js +76 -0
- package/src/server/application/agent-connection-service.js +178 -0
- package/src/server/application/agent-content-service.js +773 -0
- package/src/server/application/workspace-reconciliation.js +5 -7
- package/src/server/config/env.js +51 -1
- package/src/server/create-app-server.js +36 -0
- package/src/server/domain/bases/base-query-service.js +1 -5
- package/src/server/domain/collaboration/collaboration-room.js +121 -25
- package/src/server/domain/collaboration/protocol.js +4 -0
- package/src/server/domain/hosted-workspace.js +21 -0
- package/src/server/domain/markdown-reference-extractor.js +15 -1
- package/src/server/infrastructure/git/git-service.js +19 -1
- package/src/server/infrastructure/git/history-service.js +1 -1
- package/src/server/infrastructure/git/local-exclude.js +25 -0
- package/src/server/infrastructure/git/parsers.js +19 -17
- package/src/server/infrastructure/git/path-utils.js +0 -16
- package/src/server/infrastructure/git/status-service.js +1 -1
- package/src/server/infrastructure/git/untracked-files.js +12 -21
- package/src/server/infrastructure/http/create-agent-api-handler.js +171 -0
- package/src/server/infrastructure/http/create-git-api-command-handler.js +32 -0
- package/src/server/infrastructure/http/create-request-handler.js +28 -0
- package/src/server/infrastructure/http/create-static-handler.js +6 -0
- package/src/server/infrastructure/mcp/create-agent-mcp-handler.js +199 -0
- package/src/server/infrastructure/persistence/agent-connection-store.js +120 -0
- package/src/server/infrastructure/persistence/pull-backup-store.js +2 -27
- package/src/server/infrastructure/persistence/vault-file-store.js +9 -2
- package/src/server/shared/agent-tool-image.js +22 -0
- package/src/server/shared/agent-tool-rate-limiter.js +20 -0
- package/src/server/startup/git-remote-bootstrap.js +5 -33
- package/dist/client/assets/CodeMirrorEditor-UCMRAMCV-BPH4FJkv.js +0 -1
- package/dist/client/assets/abnfDiagram-VCTEODGH-BNDLzJ7L.js +0 -1
- package/dist/client/assets/browser-utils--H_DkyEF.js +0 -1
- package/dist/client/assets/channel-CaoKA_We.js +0 -1
- package/dist/client/assets/chunk-DSNCTWBM-8xkug7fQ.js +0 -2
- package/dist/client/assets/chunk-DU6HZSFF-COXDzJK1.js +0 -127
- package/dist/client/assets/chunk-R7TYR2AO-CTd0Yj98.js +0 -10
- package/dist/client/assets/classDiagram-DTDB5LWJ-7fEmn0zV.js +0 -1
- package/dist/client/assets/classDiagram-v2-JRS7N3AN-7fEmn0zV.js +0 -1
- package/dist/client/assets/comment-threads-9J6Em-_y.js +0 -4
- package/dist/client/assets/comment-ui-shared-DuoyznXW.js +0 -7
- package/dist/client/assets/diagram-VSXAHHWV-CQRVEZR7.js +0 -3
- package/dist/client/assets/dist-73RPdcyU.js +0 -1
- package/dist/client/assets/dist-CH-sQu3r.js +0 -1
- package/dist/client/assets/document-formatter-Dxl_a8XO.js +0 -2
- package/dist/client/assets/drawio-editor-BVaNNtYp.js +0 -9
- package/dist/client/assets/drawioEditor-BkIBlXx0.js +0 -2
- package/dist/client/assets/ebnfDiagram-PWID7BFC-OXa8VEp1.js +0 -1
- package/dist/client/assets/editor-session-DMyVdHLj.js +0 -54
- package/dist/client/assets/excalidraw-editor-BjYaNEMY.js +0 -9
- package/dist/client/assets/excalidraw-mermaid-stub-BNckbX2n.js +0 -1
- package/dist/client/assets/excalidraw-mermaid-stub-DE5FTiZB.js +0 -1
- package/dist/client/assets/excalidrawEditor-ChqF_d82.js +0 -2
- package/dist/client/assets/export-page-Dyu0XCbu.js +0 -57
- package/dist/client/assets/exportDocument-CJBx4Xjx.css +0 -1
- package/dist/client/assets/exportDocument-Dgvfa2Sd.js +0 -2
- package/dist/client/assets/flowDiagram-A5DVABFB-CiW1eN8C.js +0 -1
- package/dist/client/assets/image-ZVKINSPA-0zXSnE7M.js +0 -1
- package/dist/client/assets/index-CSNIMyOP.css +0 -1
- package/dist/client/assets/index-DG3N2Ps-.js +0 -2
- package/dist/client/assets/main-D0wCxpVn.js +0 -903
- package/dist/client/assets/mermaid.core-BJRLUQZE.js +0 -11
- package/dist/client/assets/pegDiagram-XKGWAZYB-B31fKPR2.js +0 -1
- package/dist/client/assets/preview-render-compiler-CrJIooVD.js +0 -35
- package/dist/client/assets/preview-render-compiler-O0JxBVNF.js +0 -1
- package/dist/client/assets/preview-render-profile-B4RWYWHt.js +0 -1
- package/dist/client/assets/prod-BiYPMR1i.js +0 -177
- package/dist/client/assets/prod-VxdGZ5Ly.js +0 -1
- package/dist/client/assets/quick-switcher-controller-CaEjEtq_.js +0 -1
- package/dist/client/assets/railroadDiagram-O6MQD6OU-BPifP0MB.js +0 -1
- package/dist/client/assets/runtime-config-BLrEKVO1.js +0 -1
- package/dist/client/assets/stateDiagram-v2-4QOOHH4V-B--gjrit.js +0 -1
- package/dist/client/assets/swimlanesDiagram-VK2B7HYN-DO8XNXEg.js +0 -8
- package/dist/client/assets/vault-api-client-BkwdFjx0.js +0 -6
- package/src/client/app/drawio-editor-entry.js +0 -1
- package/src/client/app/excalidraw-editor-entry.js +0 -1
- package/src/client/excalidraw-mermaid-stub.js +0 -7
- package/src/client/main.js +0 -16
- /package/dist/client/assets/{drawio-editor-UQQ8XHou.css → drawioEditor-UQQ8XHou.css} +0 -0
- /package/dist/client/assets/{excalidraw-editor-BbSbI80a.css → excalidrawEditor-BbSbI80a.css} +0 -0
- /package/dist/client/assets/{sizeCapture-X5ZJPWSS-B0uUizjq.js → sizeCapture-INFHLROL-B0uUizjq.js} +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createExcalidrawExportOptions } from '../domain/excalidraw-scene.js';
|
|
1
2
|
import { escapeHtml } from '../domain/vault-utils.js';
|
|
2
3
|
import { commitButtonLabel } from '../domain/git-labels.js';
|
|
3
4
|
import { getVaultPathLeaf, getVaultPathParent } from '../domain/vault-paths.js';
|
|
@@ -200,29 +201,25 @@ function getDrawioSourcePair(detail = {}) {
|
|
|
200
201
|
};
|
|
201
202
|
}
|
|
202
203
|
|
|
203
|
-
function decodeXmlAttribute(value) {
|
|
204
|
-
return String(value ?? '')
|
|
205
|
-
.replace(/"/gu, '"')
|
|
206
|
-
.replace(/'/gu, "'")
|
|
207
|
-
.replace(/&/gu, '&')
|
|
208
|
-
.replace(/</gu, '<')
|
|
209
|
-
.replace(/>/gu, '>');
|
|
210
|
-
}
|
|
211
|
-
|
|
212
204
|
function getDrawioCellMap(source) {
|
|
213
205
|
const cells = new Map();
|
|
214
|
-
|
|
215
|
-
|
|
206
|
+
if (typeof DOMParser === 'undefined' || typeof XMLSerializer === 'undefined') {
|
|
207
|
+
return cells;
|
|
208
|
+
}
|
|
216
209
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
210
|
+
const documentNode = new DOMParser().parseFromString(String(source ?? ''), 'application/xml');
|
|
211
|
+
if (documentNode.querySelector('parsererror')) {
|
|
212
|
+
return cells;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const serializer = new XMLSerializer();
|
|
216
|
+
for (const cell of documentNode.getElementsByTagName('mxCell')) {
|
|
217
|
+
const id = cell.getAttribute('id');
|
|
220
218
|
if (!id || id === '0' || id === '1') {
|
|
221
219
|
continue;
|
|
222
220
|
}
|
|
223
221
|
|
|
224
|
-
|
|
225
|
-
cells.set(id, signature);
|
|
222
|
+
cells.set(id, serializer.serializeToString(cell).replace(/\s+/gu, ' ').trim());
|
|
226
223
|
}
|
|
227
224
|
|
|
228
225
|
return cells;
|
|
@@ -647,7 +644,7 @@ export class GitDiffViewController {
|
|
|
647
644
|
this.excalidrawPreviewPayloads.clear();
|
|
648
645
|
this.drawioPreviewPayloads.clear();
|
|
649
646
|
this.requestScope = scope;
|
|
650
|
-
this.renderLoading('Loading diff summary
|
|
647
|
+
this.renderLoading('Loading diff summary…');
|
|
651
648
|
|
|
652
649
|
try {
|
|
653
650
|
const data = await this.gitApiClient.readDiff({
|
|
@@ -677,7 +674,7 @@ export class GitDiffViewController {
|
|
|
677
674
|
source: 'workspace',
|
|
678
675
|
summary: { additions: 0, deletions: 0, filesChanged: 0 },
|
|
679
676
|
};
|
|
680
|
-
this.renderEmpty('Failed to load git diff');
|
|
677
|
+
this.renderEmpty('Failed to load git diff', { alert: true });
|
|
681
678
|
return this.data;
|
|
682
679
|
}
|
|
683
680
|
}
|
|
@@ -700,7 +697,7 @@ export class GitDiffViewController {
|
|
|
700
697
|
this.excalidrawPreviewPayloads.clear();
|
|
701
698
|
this.drawioPreviewPayloads.clear();
|
|
702
699
|
this.requestScope = 'all';
|
|
703
|
-
this.renderLoading('Loading commit summary
|
|
700
|
+
this.renderLoading('Loading commit summary…');
|
|
704
701
|
|
|
705
702
|
try {
|
|
706
703
|
const data = await this.gitApiClient.readCommit({
|
|
@@ -741,7 +738,7 @@ export class GitDiffViewController {
|
|
|
741
738
|
summary: { additions: 0, deletions: 0, filesChanged: 0 },
|
|
742
739
|
};
|
|
743
740
|
this.commitMeta = null;
|
|
744
|
-
this.renderEmpty('Failed to load git commit');
|
|
741
|
+
this.renderEmpty('Failed to load git commit', { alert: true });
|
|
745
742
|
return this.data;
|
|
746
743
|
}
|
|
747
744
|
}
|
|
@@ -790,27 +787,27 @@ export class GitDiffViewController {
|
|
|
790
787
|
void this.loadCurrentFile();
|
|
791
788
|
}
|
|
792
789
|
|
|
793
|
-
renderLoading(message = 'Loading git diff
|
|
790
|
+
renderLoading(message = 'Loading git diff…') {
|
|
794
791
|
if (!this.isActive) {
|
|
795
792
|
return;
|
|
796
793
|
}
|
|
797
794
|
this.page?.classList.remove('hidden');
|
|
798
795
|
if (this.content) {
|
|
799
796
|
// pi-lens-ignore: ast-grep:no-inner-html-js
|
|
800
|
-
this.content.innerHTML = `<div class="diff-empty-state">${escapeHtml(message)}</div>`;
|
|
797
|
+
this.content.innerHTML = `<div class="diff-empty-state" role="status" aria-live="polite">${escapeHtml(message)}</div>`;
|
|
801
798
|
}
|
|
802
799
|
this.data = null;
|
|
803
800
|
this.syncToolbar();
|
|
804
801
|
}
|
|
805
802
|
|
|
806
|
-
renderEmpty(message) {
|
|
803
|
+
renderEmpty(message, { alert = false } = {}) {
|
|
807
804
|
if (!this.isActive) {
|
|
808
805
|
return;
|
|
809
806
|
}
|
|
810
807
|
this.page?.classList.remove('hidden');
|
|
811
808
|
if (this.content) {
|
|
812
809
|
// pi-lens-ignore: ast-grep:no-inner-html-js
|
|
813
|
-
this.content.innerHTML = `<div class="diff-empty-state">${escapeHtml(message)}</div>`;
|
|
810
|
+
this.content.innerHTML = `<div class="diff-empty-state"${alert ? ' role="alert"' : ''}>${escapeHtml(message)}</div>`;
|
|
814
811
|
}
|
|
815
812
|
this.syncToolbar();
|
|
816
813
|
}
|
|
@@ -1194,16 +1191,7 @@ export class GitDiffViewController {
|
|
|
1194
1191
|
}
|
|
1195
1192
|
|
|
1196
1193
|
try {
|
|
1197
|
-
const svg = await exportToSvg(
|
|
1198
|
-
appState: {
|
|
1199
|
-
exportBackground: true,
|
|
1200
|
-
exportWithDarkMode: false,
|
|
1201
|
-
viewBackgroundColor: scene.appState?.viewBackgroundColor || '#ffffff',
|
|
1202
|
-
},
|
|
1203
|
-
elements: getVisibleSceneElements(scene),
|
|
1204
|
-
exportPadding: 24,
|
|
1205
|
-
files: scene.files || null,
|
|
1206
|
-
});
|
|
1194
|
+
const svg = await exportToSvg(createExcalidrawExportOptions(scene));
|
|
1207
1195
|
preview.replaceChildren(svg);
|
|
1208
1196
|
preview.classList.add('is-ready');
|
|
1209
1197
|
} catch (error) {
|
|
@@ -1345,7 +1333,7 @@ export class GitDiffViewController {
|
|
|
1345
1333
|
return `
|
|
1346
1334
|
<section class="diff-file-block">
|
|
1347
1335
|
${this.renderFileHeader(currentFile)}
|
|
1348
|
-
<div class="diff-empty-state">Loading file diff
|
|
1336
|
+
<div class="diff-empty-state" role="status" aria-live="polite">Loading file diff…</div>
|
|
1349
1337
|
</section>
|
|
1350
1338
|
`;
|
|
1351
1339
|
}
|
|
@@ -1355,7 +1343,7 @@ export class GitDiffViewController {
|
|
|
1355
1343
|
return `
|
|
1356
1344
|
<section class="diff-file-block">
|
|
1357
1345
|
${this.renderFileHeader(currentFile)}
|
|
1358
|
-
<div class="diff-empty-state">${escapeHtml(errorMessage)}</div>
|
|
1346
|
+
<div class="diff-empty-state" role="alert">${escapeHtml(errorMessage)}</div>
|
|
1359
1347
|
</section>
|
|
1360
1348
|
`;
|
|
1361
1349
|
}
|
|
@@ -1435,9 +1423,9 @@ export class GitDiffViewController {
|
|
|
1435
1423
|
const bodyMarkup = isCollapsed
|
|
1436
1424
|
? ''
|
|
1437
1425
|
: isLoading
|
|
1438
|
-
? '<div class="diff-empty-state">Loading file diff
|
|
1426
|
+
? '<div class="diff-empty-state" role="status" aria-live="polite">Loading file diff…</div>'
|
|
1439
1427
|
: errorMessage
|
|
1440
|
-
? `<div class="diff-empty-state">${escapeHtml(errorMessage)}</div>`
|
|
1428
|
+
? `<div class="diff-empty-state" role="alert">${escapeHtml(errorMessage)}</div>`
|
|
1441
1429
|
: this.renderDiffDetail(detail, index, { includeHeader: false });
|
|
1442
1430
|
|
|
1443
1431
|
return `
|
|
@@ -1877,11 +1865,15 @@ export class GitDiffViewController {
|
|
|
1877
1865
|
}
|
|
1878
1866
|
|
|
1879
1867
|
this.modeButtons.forEach((button) => {
|
|
1868
|
+
const active = button.getAttribute('data-diff-mode') === this.mode;
|
|
1880
1869
|
button.classList.remove('hidden');
|
|
1881
|
-
button.classList.toggle('active',
|
|
1870
|
+
button.classList.toggle('active', active);
|
|
1871
|
+
button.setAttribute?.('aria-pressed', String(active));
|
|
1882
1872
|
});
|
|
1883
1873
|
this.layoutButtons.forEach((button) => {
|
|
1884
|
-
|
|
1874
|
+
const active = button.getAttribute('data-diff-layout') === this.layoutMode;
|
|
1875
|
+
button.classList.toggle('active', active);
|
|
1876
|
+
button.setAttribute?.('aria-pressed', String(active));
|
|
1885
1877
|
});
|
|
1886
1878
|
|
|
1887
1879
|
const hasCurrentFile = Boolean(this.getCurrentFile()?.path);
|
|
@@ -1906,8 +1898,8 @@ export class GitDiffViewController {
|
|
|
1906
1898
|
this.primaryActionButton.classList.toggle('ui-button--primary', emphasizeInclude);
|
|
1907
1899
|
this.primaryActionButton.classList.toggle('ui-button--secondary', !emphasizeInclude);
|
|
1908
1900
|
this.primaryActionButton.classList.toggle('ui-button--surface', !emphasizeInclude);
|
|
1909
|
-
this.primaryActionButton.textContent = this.pendingAction === primaryAction
|
|
1910
|
-
? 'Working
|
|
1901
|
+
this.primaryActionButton.textContent = this.pendingAction && this.pendingAction === primaryAction
|
|
1902
|
+
? 'Working…'
|
|
1911
1903
|
: primaryAction === 'unstage'
|
|
1912
1904
|
? 'Remove'
|
|
1913
1905
|
: 'Include in commit';
|
|
@@ -1918,7 +1910,7 @@ export class GitDiffViewController {
|
|
|
1918
1910
|
}
|
|
1919
1911
|
if (this.commitButton) {
|
|
1920
1912
|
this.commitButton.textContent = this.pendingAction === 'commit'
|
|
1921
|
-
? 'Working
|
|
1913
|
+
? 'Working…'
|
|
1922
1914
|
: commitButtonLabel(includedFileCount);
|
|
1923
1915
|
}
|
|
1924
1916
|
this.commitButton?.classList.toggle(
|
|
@@ -94,7 +94,9 @@ export class GitPanelController {
|
|
|
94
94
|
onResetFile = () => {},
|
|
95
95
|
onSelectCommit = () => {},
|
|
96
96
|
onSelectDiff = () => {},
|
|
97
|
+
onStageAll = () => {},
|
|
97
98
|
onStageFile = () => {},
|
|
99
|
+
onUnstageAll = () => {},
|
|
98
100
|
onUnstageFile = () => {},
|
|
99
101
|
onViewAllDiff = () => {},
|
|
100
102
|
searchInput = null,
|
|
@@ -110,7 +112,9 @@ export class GitPanelController {
|
|
|
110
112
|
this.onResetFile = onResetFile;
|
|
111
113
|
this.onSelectCommit = onSelectCommit;
|
|
112
114
|
this.onSelectDiff = onSelectDiff;
|
|
115
|
+
this.onStageAll = onStageAll;
|
|
113
116
|
this.onStageFile = onStageFile;
|
|
117
|
+
this.onUnstageAll = onUnstageAll;
|
|
114
118
|
this.onUnstageFile = onUnstageFile;
|
|
115
119
|
this.onViewAllDiff = onViewAllDiff;
|
|
116
120
|
this.searchInput = searchInput;
|
|
@@ -118,6 +122,7 @@ export class GitPanelController {
|
|
|
118
122
|
this.panel = document.getElementById('gitPanel');
|
|
119
123
|
this.pullBackups = [];
|
|
120
124
|
this.status = null;
|
|
125
|
+
this.statusError = '';
|
|
121
126
|
this.active = false;
|
|
122
127
|
this.refreshTimer = null;
|
|
123
128
|
this.searchQuery = '';
|
|
@@ -236,6 +241,17 @@ export class GitPanelController {
|
|
|
236
241
|
|
|
237
242
|
if (this._handleFileActionClick(event)) return;
|
|
238
243
|
|
|
244
|
+
const bulkActionButton = event.target instanceof Element
|
|
245
|
+
? event.target.closest('[data-git-bulk-action]')
|
|
246
|
+
: null;
|
|
247
|
+
if (bulkActionButton) {
|
|
248
|
+
const action = bulkActionButton.getAttribute('data-git-bulk-action');
|
|
249
|
+
if (action === 'stage-all' || action === 'unstage-all') {
|
|
250
|
+
void this.handleBulkAction(action);
|
|
251
|
+
}
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
|
|
239
255
|
if (event.target instanceof Element && event.target.closest('[data-git-view-all]')) {
|
|
240
256
|
this.onViewAllDiff();
|
|
241
257
|
return;
|
|
@@ -377,7 +393,7 @@ export class GitPanelController {
|
|
|
377
393
|
|
|
378
394
|
async refresh({ force = false, includeHistory = this.panelMode === 'history' } = {}) {
|
|
379
395
|
const status = await this.refreshStatus({ force });
|
|
380
|
-
if (includeHistory && status
|
|
396
|
+
if (includeHistory && status?.isGitRepo) {
|
|
381
397
|
await this.refreshHistory({ force });
|
|
382
398
|
}
|
|
383
399
|
return status;
|
|
@@ -385,6 +401,7 @@ export class GitPanelController {
|
|
|
385
401
|
|
|
386
402
|
async refreshStatus({ force = false } = {}) {
|
|
387
403
|
if (!this.enabled) {
|
|
404
|
+
this.statusError = '';
|
|
388
405
|
this.status = {
|
|
389
406
|
isGitRepo: false,
|
|
390
407
|
sections: [],
|
|
@@ -409,6 +426,7 @@ export class GitPanelController {
|
|
|
409
426
|
try {
|
|
410
427
|
const data = await this.gitApiClient.readStatus({ force });
|
|
411
428
|
this.status = data;
|
|
429
|
+
this.statusError = '';
|
|
412
430
|
this.pullBackups = [];
|
|
413
431
|
if (data.isGitRepo) {
|
|
414
432
|
try {
|
|
@@ -435,25 +453,9 @@ export class GitPanelController {
|
|
|
435
453
|
} catch (error) {
|
|
436
454
|
console.error('[git-panel] Failed to load git status:', error);
|
|
437
455
|
this.toastController?.show('Failed to load git status');
|
|
438
|
-
this.
|
|
439
|
-
isGitRepo: false,
|
|
440
|
-
sections: [],
|
|
441
|
-
summary: { changedFiles: 0 },
|
|
442
|
-
};
|
|
443
|
-
this.pullBackups = [];
|
|
444
|
-
this.history = {
|
|
445
|
-
...this.history,
|
|
446
|
-
commits: [],
|
|
447
|
-
error: '',
|
|
448
|
-
hasMore: false,
|
|
449
|
-
loaded: false,
|
|
450
|
-
loading: false,
|
|
451
|
-
loadingMore: false,
|
|
452
|
-
offset: 0,
|
|
453
|
-
};
|
|
454
|
-
this.onRepoChange(false, this.status);
|
|
456
|
+
this.statusError = 'Failed to load Git status. Try again.';
|
|
455
457
|
this.render();
|
|
456
|
-
return
|
|
458
|
+
return null;
|
|
457
459
|
}
|
|
458
460
|
}
|
|
459
461
|
|
|
@@ -615,6 +617,22 @@ export class GitPanelController {
|
|
|
615
617
|
}
|
|
616
618
|
}
|
|
617
619
|
|
|
620
|
+
async handleBulkAction(action) {
|
|
621
|
+
if (this.pendingActionKey) {
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
this.pendingActionKey = action;
|
|
626
|
+
this.render();
|
|
627
|
+
|
|
628
|
+
try {
|
|
629
|
+
await (action === 'stage-all' ? this.onStageAll() : this.onUnstageAll());
|
|
630
|
+
} finally {
|
|
631
|
+
this.pendingActionKey = null;
|
|
632
|
+
this.render();
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
618
636
|
async handleCommitStaged() {
|
|
619
637
|
const actionKey = 'commit-staged';
|
|
620
638
|
if (this.pendingActionKey === actionKey) {
|
|
@@ -835,11 +853,11 @@ export class GitPanelController {
|
|
|
835
853
|
const commits = this.filterCommits(this.history.commits);
|
|
836
854
|
|
|
837
855
|
if (this.history.loading && !this.history.loaded) {
|
|
838
|
-
return '<div class="git-panel-empty">Loading git history
|
|
856
|
+
return '<div class="git-panel-empty" role="status" aria-live="polite">Loading git history…</div>';
|
|
839
857
|
}
|
|
840
858
|
|
|
841
859
|
if (this.history.error && !this.history.loaded) {
|
|
842
|
-
return `<div class="git-panel-empty">${escapeHtml(this.history.error)}</div>`;
|
|
860
|
+
return `<div class="git-panel-empty" role="alert">${escapeHtml(this.history.error)}</div>`;
|
|
843
861
|
}
|
|
844
862
|
|
|
845
863
|
if (this.history.loaded && commits.length === 0 && this.history.commits.length === 0) {
|
|
@@ -862,7 +880,7 @@ export class GitPanelController {
|
|
|
862
880
|
data-git-history-load-more
|
|
863
881
|
${this.history.loadingMore ? 'disabled' : ''}
|
|
864
882
|
>
|
|
865
|
-
${this.history.loadingMore ? 'Loading
|
|
883
|
+
${this.history.loadingMore ? 'Loading…' : 'Load more'}
|
|
866
884
|
</button>
|
|
867
885
|
</div>
|
|
868
886
|
` : ''}
|
|
@@ -877,6 +895,8 @@ export class GitPanelController {
|
|
|
877
895
|
.join('');
|
|
878
896
|
const hasChanges = Boolean(this.status.summary?.changedFiles);
|
|
879
897
|
const includedFileCount = Number(this.status.summary?.staged || 0);
|
|
898
|
+
const excludedFileCount = Number(this.status.summary?.workingTree || 0)
|
|
899
|
+
+ Number(this.status.summary?.untracked || 0);
|
|
880
900
|
const isCommitPending = this.pendingActionKey === 'commit-staged';
|
|
881
901
|
|
|
882
902
|
return `
|
|
@@ -885,9 +905,29 @@ export class GitPanelController {
|
|
|
885
905
|
${hasChanges ? `
|
|
886
906
|
<div class="git-panel-footer">
|
|
887
907
|
<div class="git-panel-footer-actions">
|
|
908
|
+
${excludedFileCount > 0 ? `
|
|
909
|
+
<button
|
|
910
|
+
class="${buttonClassNames({ variant: 'secondary', size: 'compact', action: true, surface: true })}"
|
|
911
|
+
type="button"
|
|
912
|
+
data-git-bulk-action="stage-all"
|
|
913
|
+
${this.pendingActionKey ? 'disabled' : ''}
|
|
914
|
+
>
|
|
915
|
+
${this.pendingActionKey === 'stage-all' ? 'Working...' : 'Include all changes'}
|
|
916
|
+
</button>
|
|
917
|
+
` : ''}
|
|
918
|
+
${includedFileCount > 0 ? `
|
|
919
|
+
<button
|
|
920
|
+
class="${buttonClassNames({ variant: 'secondary', size: 'compact', action: true, surface: true })}"
|
|
921
|
+
type="button"
|
|
922
|
+
data-git-bulk-action="unstage-all"
|
|
923
|
+
${this.pendingActionKey ? 'disabled' : ''}
|
|
924
|
+
>
|
|
925
|
+
${this.pendingActionKey === 'unstage-all' ? 'Working...' : 'Remove all from commit'}
|
|
926
|
+
</button>
|
|
927
|
+
` : ''}
|
|
888
928
|
<button class="${buttonClassNames({ variant: 'secondary', size: 'compact', action: true, surface: true })}" type="button" data-git-view-all>
|
|
889
929
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M2 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>
|
|
890
|
-
View
|
|
930
|
+
View full diff
|
|
891
931
|
</button>
|
|
892
932
|
<button
|
|
893
933
|
class="${buttonClassNames({ variant: 'primary', action: true, wide: true, extra: 'git-footer-commit-btn' })}"
|
|
@@ -895,7 +935,7 @@ export class GitPanelController {
|
|
|
895
935
|
data-git-commit-staged
|
|
896
936
|
${includedFileCount === 0 || isCommitPending ? 'disabled' : ''}
|
|
897
937
|
>
|
|
898
|
-
${isCommitPending ? 'Working
|
|
938
|
+
${isCommitPending ? 'Working…' : commitButtonLabel(includedFileCount)}
|
|
899
939
|
</button>
|
|
900
940
|
</div>
|
|
901
941
|
</div>
|
|
@@ -903,14 +943,19 @@ export class GitPanelController {
|
|
|
903
943
|
`;
|
|
904
944
|
}
|
|
905
945
|
|
|
906
|
-
renderEmpty(message) {
|
|
946
|
+
renderEmpty(message, { alert = false, status = false } = {}) {
|
|
907
947
|
if (!this.panel) {
|
|
908
948
|
return;
|
|
909
949
|
}
|
|
910
950
|
|
|
951
|
+
const semantics = alert
|
|
952
|
+
? ' role="alert"'
|
|
953
|
+
: status
|
|
954
|
+
? ' role="status" aria-live="polite"'
|
|
955
|
+
: '';
|
|
911
956
|
// pi-lens-ignore: ast-grep:no-inner-html-js
|
|
912
957
|
this.panel.innerHTML = `
|
|
913
|
-
<div class="git-panel-empty ui-empty-state ui-empty-state--compact">
|
|
958
|
+
<div class="git-panel-empty ui-empty-state ui-empty-state--compact"${semantics}>
|
|
914
959
|
<p class="ui-empty-state-copy">${escapeHtml(message)}</p>
|
|
915
960
|
</div>
|
|
916
961
|
`;
|
|
@@ -921,8 +966,13 @@ export class GitPanelController {
|
|
|
921
966
|
return;
|
|
922
967
|
}
|
|
923
968
|
|
|
969
|
+
if (this.statusError) {
|
|
970
|
+
this.renderEmpty(this.statusError, { alert: true });
|
|
971
|
+
return;
|
|
972
|
+
}
|
|
973
|
+
|
|
924
974
|
if (!this.status) {
|
|
925
|
-
this.renderEmpty('Loading git status
|
|
975
|
+
this.renderEmpty('Loading git status…', { status: true });
|
|
926
976
|
return;
|
|
927
977
|
}
|
|
928
978
|
|
|
@@ -76,6 +76,8 @@ export class ImageLightboxController {
|
|
|
76
76
|
this.pinchStartCenter = { x: 0, y: 0 };
|
|
77
77
|
this.didDrag = false;
|
|
78
78
|
this.resetButton = null;
|
|
79
|
+
this.previouslyFocusedElement = null;
|
|
80
|
+
this.blockingModalHandler = () => this.close();
|
|
79
81
|
|
|
80
82
|
this.handlePreviewClick = (event) => {
|
|
81
83
|
const target = event.target;
|
|
@@ -102,12 +104,6 @@ export class ImageLightboxController {
|
|
|
102
104
|
return;
|
|
103
105
|
}
|
|
104
106
|
|
|
105
|
-
if (event.key === 'Escape') {
|
|
106
|
-
event.preventDefault();
|
|
107
|
-
this.close();
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
107
|
if (event.key === '+' || event.key === '=') {
|
|
112
108
|
event.preventDefault();
|
|
113
109
|
this.zoomBy(ZOOM_STEP);
|
|
@@ -161,15 +157,19 @@ export class ImageLightboxController {
|
|
|
161
157
|
}
|
|
162
158
|
|
|
163
159
|
this.ensureOverlayRoot();
|
|
160
|
+
this.previouslyFocusedElement = this.document.activeElement instanceof this.window.HTMLElement
|
|
161
|
+
? this.document.activeElement
|
|
162
|
+
: null;
|
|
164
163
|
this.resetView();
|
|
165
164
|
this.titleElement.textContent = image.getAttribute('alt') || 'Image preview';
|
|
166
165
|
this.imageElement.src = src;
|
|
167
166
|
this.imageElement.alt = image.getAttribute('alt') || '';
|
|
168
|
-
this.overlayRoot.
|
|
167
|
+
this.overlayRoot.showModal();
|
|
169
168
|
this.isOpen = true;
|
|
170
169
|
this.document.body.classList.add('image-lightbox-open');
|
|
170
|
+
this.document.addEventListener('collabmd:close-custom-modals', this.blockingModalHandler);
|
|
171
171
|
this.syncTransform();
|
|
172
|
-
this.overlayRoot.focus
|
|
172
|
+
this.overlayRoot.querySelector('button:not(:disabled)')?.focus();
|
|
173
173
|
return true;
|
|
174
174
|
}
|
|
175
175
|
|
|
@@ -184,11 +184,14 @@ export class ImageLightboxController {
|
|
|
184
184
|
this.pinchStartDistance = 0;
|
|
185
185
|
this.didDrag = false;
|
|
186
186
|
this.viewport?.classList?.remove('is-dragging');
|
|
187
|
-
if (this.overlayRoot) {
|
|
188
|
-
this.overlayRoot.
|
|
187
|
+
if (this.overlayRoot?.open) {
|
|
188
|
+
this.overlayRoot.close();
|
|
189
189
|
}
|
|
190
190
|
this.isOpen = false;
|
|
191
191
|
this.document.body.classList.remove('image-lightbox-open');
|
|
192
|
+
this.document.removeEventListener('collabmd:close-custom-modals', this.blockingModalHandler);
|
|
193
|
+
this.previouslyFocusedElement?.focus?.();
|
|
194
|
+
this.previouslyFocusedElement = null;
|
|
192
195
|
}
|
|
193
196
|
|
|
194
197
|
resetView() {
|
|
@@ -442,11 +445,14 @@ export class ImageLightboxController {
|
|
|
442
445
|
return this.overlayRoot;
|
|
443
446
|
}
|
|
444
447
|
|
|
445
|
-
const overlayRoot = this.document.createElement('
|
|
448
|
+
const overlayRoot = this.document.createElement('dialog');
|
|
446
449
|
overlayRoot.className = 'image-lightbox-root';
|
|
447
450
|
overlayRoot.dataset.imageLightboxRoot = 'true';
|
|
448
|
-
overlayRoot.
|
|
449
|
-
overlayRoot.
|
|
451
|
+
overlayRoot.setAttribute('aria-labelledby', 'imageLightboxTitle');
|
|
452
|
+
overlayRoot.addEventListener('cancel', (event) => {
|
|
453
|
+
event.preventDefault();
|
|
454
|
+
this.close();
|
|
455
|
+
});
|
|
450
456
|
|
|
451
457
|
const backdrop = this.document.createElement('button');
|
|
452
458
|
backdrop.className = 'image-lightbox-backdrop';
|
|
@@ -460,9 +466,6 @@ export class ImageLightboxController {
|
|
|
460
466
|
|
|
461
467
|
const shell = this.document.createElement('div');
|
|
462
468
|
shell.className = 'image-lightbox-shell';
|
|
463
|
-
shell.setAttribute('role', 'dialog');
|
|
464
|
-
shell.setAttribute('aria-modal', 'true');
|
|
465
|
-
shell.setAttribute('aria-label', 'Image preview');
|
|
466
469
|
shell.addEventListener('click', (event) => event.stopPropagation());
|
|
467
470
|
shell.addEventListener('pointerdown', (event) => event.stopPropagation());
|
|
468
471
|
|
|
@@ -471,6 +474,7 @@ export class ImageLightboxController {
|
|
|
471
474
|
|
|
472
475
|
const title = this.document.createElement('div');
|
|
473
476
|
title.className = 'image-lightbox-title';
|
|
477
|
+
title.id = 'imageLightboxTitle';
|
|
474
478
|
title.textContent = 'Image preview';
|
|
475
479
|
|
|
476
480
|
const controls = this.document.createElement('div');
|
|
@@ -15,7 +15,7 @@ export class LayoutController {
|
|
|
15
15
|
this.previewPane = document.getElementById('previewPane');
|
|
16
16
|
this.mobileToggleButton = document.getElementById('mobileViewToggle');
|
|
17
17
|
this.resizer = document.getElementById('resizer');
|
|
18
|
-
this.viewButtons = Array.from(document.querySelectorAll('
|
|
18
|
+
this.viewButtons = Array.from(document.querySelectorAll('#toolbarViewToggle [data-view]'));
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
isMobileViewport() {
|
|
@@ -128,6 +128,8 @@ export class LayoutController {
|
|
|
128
128
|
const previewIcon = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>';
|
|
129
129
|
const editorIcon = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="8" y1="8" x2="16" y2="8"/><line x1="8" y1="12" x2="14" y2="12"/><line x1="8" y1="16" x2="12" y2="16"/></svg>';
|
|
130
130
|
|
|
131
|
+
// Icons and labels are fixed application-owned markup.
|
|
132
|
+
// pi-lens-ignore: no-inner-html-js
|
|
131
133
|
this.mobileToggleButton.innerHTML = `${label === 'Editor' ? editorIcon : previewIcon}<span class="ui-toolbar-button-label">${label}</span>`;
|
|
132
134
|
}
|
|
133
135
|
|
|
@@ -98,28 +98,20 @@ export class QuickSwitcherController {
|
|
|
98
98
|
this.selectedIndex = 0;
|
|
99
99
|
this.selectedTextIndex = 0;
|
|
100
100
|
this.isOpen = false;
|
|
101
|
-
this.previousActiveElement = null;
|
|
102
101
|
this.mode = 'files';
|
|
103
102
|
this.textResults = null;
|
|
104
103
|
this.textResultItems = [];
|
|
105
104
|
this.textSearchRunner = new QuickSwitcherTextSearchRunner({
|
|
106
105
|
debounceMs: this.searchDebounceMs,
|
|
107
106
|
});
|
|
107
|
+
this.blockingModalHandler = () => this.close();
|
|
108
108
|
|
|
109
109
|
this.bindEvents();
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
bindEvents() {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
this.overlay?.addEventListener('keydown', (e) => {
|
|
118
|
-
if (e.key === 'Escape') {
|
|
119
|
-
e.preventDefault();
|
|
120
|
-
this.close();
|
|
121
|
-
}
|
|
122
|
-
});
|
|
113
|
+
document.addEventListener?.('collabmd:close-custom-modals', this.blockingModalHandler);
|
|
114
|
+
this.overlay?.addEventListener('close', () => this.handleClose());
|
|
123
115
|
|
|
124
116
|
this.modeTabs.forEach((tab, index) => {
|
|
125
117
|
tab.addEventListener('click', () => {
|
|
@@ -173,86 +165,36 @@ export class QuickSwitcherController {
|
|
|
173
165
|
});
|
|
174
166
|
}
|
|
175
167
|
|
|
168
|
+
handleClose() {
|
|
169
|
+
this.abortTextSearch();
|
|
170
|
+
this.isOpen = false;
|
|
171
|
+
this.input?.setAttribute('aria-expanded', 'false');
|
|
172
|
+
this.input.value = '';
|
|
173
|
+
this.resultsList.innerHTML = '';
|
|
174
|
+
this.setActiveDescendant('');
|
|
175
|
+
}
|
|
176
|
+
|
|
176
177
|
open() {
|
|
177
|
-
if (!this.overlay) return;
|
|
178
|
+
if (!this.overlay || this.overlay.open) return;
|
|
178
179
|
|
|
179
|
-
this.previousActiveElement = document.activeElement;
|
|
180
180
|
this.isOpen = true;
|
|
181
181
|
this.input.value = '';
|
|
182
182
|
this.selectedIndex = 0;
|
|
183
183
|
this.selectedTextIndex = 0;
|
|
184
|
-
this.overlay.classList.add('visible');
|
|
185
|
-
this.overlay.setAttribute('aria-hidden', 'false');
|
|
186
|
-
this.input?.setAttribute('aria-expanded', 'true');
|
|
187
184
|
this.setMode('files', { preserveInput: true });
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
// Browsers ignore .focus() while the element is still visibility:hidden,
|
|
191
|
-
// so we must wait for the transition to complete.
|
|
192
|
-
this._focusAfterTransition();
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/** Focus the input once the overlay visibility transition finishes. */
|
|
196
|
-
_focusAfterTransition() {
|
|
197
|
-
this._cancelPendingFocus();
|
|
198
|
-
|
|
199
|
-
const tryFocus = () => {
|
|
200
|
-
this._focusCleanup = null;
|
|
201
|
-
this.input?.focus();
|
|
202
|
-
if (this.isOpen && this.input && document.activeElement !== this.input) {
|
|
203
|
-
setTimeout(() => this.input?.focus(), 50);
|
|
204
|
-
}
|
|
205
|
-
};
|
|
206
|
-
|
|
207
|
-
const onEnd = (e) => {
|
|
208
|
-
if (e.propertyName === 'visibility' || e.propertyName === 'opacity') {
|
|
209
|
-
this.overlay.removeEventListener('transitionend', onEnd);
|
|
210
|
-
clearTimeout(fallbackTimer);
|
|
211
|
-
tryFocus();
|
|
212
|
-
}
|
|
213
|
-
};
|
|
214
|
-
this.overlay.addEventListener('transitionend', onEnd);
|
|
215
|
-
|
|
216
|
-
const fallbackTimer = setTimeout(() => {
|
|
217
|
-
this.overlay.removeEventListener('transitionend', onEnd);
|
|
218
|
-
tryFocus();
|
|
219
|
-
}, 160);
|
|
220
|
-
|
|
221
|
-
this._focusCleanup = () => {
|
|
222
|
-
this.overlay.removeEventListener('transitionend', onEnd);
|
|
223
|
-
clearTimeout(fallbackTimer);
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
_cancelPendingFocus() {
|
|
228
|
-
if (this._focusCleanup) {
|
|
229
|
-
this._focusCleanup();
|
|
230
|
-
this._focusCleanup = null;
|
|
231
|
-
}
|
|
185
|
+
this.overlay.showModal();
|
|
186
|
+
this.input?.setAttribute('aria-expanded', 'true');
|
|
232
187
|
}
|
|
233
188
|
|
|
234
|
-
close(
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
this._cancelPendingFocus();
|
|
239
|
-
this.abortTextSearch();
|
|
240
|
-
this.isOpen = false;
|
|
241
|
-
this.overlay.classList.remove('visible');
|
|
242
|
-
this.overlay.setAttribute('aria-hidden', 'true');
|
|
243
|
-
this.input?.setAttribute('aria-expanded', 'false');
|
|
244
|
-
this.input.value = '';
|
|
245
|
-
this.resultsList.innerHTML = '';
|
|
246
|
-
this.setActiveDescendant('');
|
|
247
|
-
this.previousActiveElement = null;
|
|
248
|
-
|
|
249
|
-
if (restoreFocus) {
|
|
250
|
-
previousActiveElement?.focus?.();
|
|
189
|
+
close() {
|
|
190
|
+
this.handleClose();
|
|
191
|
+
if (this.overlay?.open) {
|
|
192
|
+
this.overlay.close();
|
|
251
193
|
}
|
|
252
194
|
}
|
|
253
195
|
|
|
254
196
|
toggle() {
|
|
255
|
-
if (this.
|
|
197
|
+
if (this.overlay?.open) {
|
|
256
198
|
this.close();
|
|
257
199
|
} else {
|
|
258
200
|
this.open();
|