@aprovan/patchwork-web 0.1.0-dev.4d82df8
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/.turbo/turbo-build.log +327 -0
- package/.utcp_config.json +65 -0
- package/LICENSE +373 -0
- package/dist/assets/__vite-browser-external-BIHI7g3E.js +1 -0
- package/dist/assets/abap-BdImnpbu.js +1 -0
- package/dist/assets/actionscript-3-CoDkCxhg.js +1 -0
- package/dist/assets/ada-bCR0ucgS.js +1 -0
- package/dist/assets/andromeeda-C4gqWexZ.js +1 -0
- package/dist/assets/angular-html-CU67Zn6k.js +1 -0
- package/dist/assets/angular-ts-BwZT4LLn.js +1 -0
- package/dist/assets/apache-Pmp26Uib.js +1 -0
- package/dist/assets/apex-D8_7TLub.js +1 -0
- package/dist/assets/apl-dKokRX4l.js +1 -0
- package/dist/assets/applescript-Co6uUVPk.js +1 -0
- package/dist/assets/ara-BRHolxvo.js +1 -0
- package/dist/assets/asciidoc-Ve4PFQV2.js +1 -0
- package/dist/assets/asm-D_Q5rh1f.js +1 -0
- package/dist/assets/astro-CbQHKStN.js +1 -0
- package/dist/assets/aurora-x-D-2ljcwZ.js +1 -0
- package/dist/assets/awk-DMzUqQB5.js +1 -0
- package/dist/assets/ayu-dark-DYE7WIF3.js +1 -0
- package/dist/assets/ayu-light-BA47KaF1.js +1 -0
- package/dist/assets/ayu-mirage-32ctXXKs.js +1 -0
- package/dist/assets/ballerina-BFfxhgS-.js +1 -0
- package/dist/assets/bat-BkioyH1T.js +1 -0
- package/dist/assets/beancount-k_qm7-4y.js +1 -0
- package/dist/assets/berry-uYugtg8r.js +1 -0
- package/dist/assets/bibtex-CHM0blh-.js +1 -0
- package/dist/assets/bicep-Bmn6On1c.js +1 -0
- package/dist/assets/bird2-DPOp833l.js +1 -0
- package/dist/assets/blade-D4QpJJKB.js +1 -0
- package/dist/assets/bsl-BO_Y6i37.js +1 -0
- package/dist/assets/c-BIGW1oBm.js +1 -0
- package/dist/assets/c3-eo99z4R2.js +1 -0
- package/dist/assets/cadence-Bv_4Rxtq.js +1 -0
- package/dist/assets/cairo-KRGpt6FW.js +1 -0
- package/dist/assets/catppuccin-frappe-DFWUc33u.js +1 -0
- package/dist/assets/catppuccin-latte-C9dUb6Cb.js +1 -0
- package/dist/assets/catppuccin-macchiato-DQyhUUbL.js +1 -0
- package/dist/assets/catppuccin-mocha-D87Tk5Gz.js +1 -0
- package/dist/assets/clarity-D53aC0YG.js +1 -0
- package/dist/assets/clojure-P80f7IUj.js +1 -0
- package/dist/assets/cmake-D1j8_8rp.js +1 -0
- package/dist/assets/cobol-nwyudZeR.js +1 -0
- package/dist/assets/codeowners-Bp6g37R7.js +1 -0
- package/dist/assets/codeql-DsOJ9woJ.js +1 -0
- package/dist/assets/coffee-Ch7k5sss.js +1 -0
- package/dist/assets/common-lisp-Cg-RD9OK.js +1 -0
- package/dist/assets/coq-DkFqJrB1.js +1 -0
- package/dist/assets/cpp-CofmeUqb.js +1 -0
- package/dist/assets/crystal-tKQVLTB8.js +1 -0
- package/dist/assets/csharp-COcwbKMJ.js +1 -0
- package/dist/assets/css-DPfMkruS.js +1 -0
- package/dist/assets/csv-fuZLfV_i.js +1 -0
- package/dist/assets/cue-D82EKSYY.js +1 -0
- package/dist/assets/cypher-COkxafJQ.js +1 -0
- package/dist/assets/d-85-TOEBH.js +1 -0
- package/dist/assets/dark-plus-C3mMm8J8.js +1 -0
- package/dist/assets/dart-CF10PKvl.js +1 -0
- package/dist/assets/dax-CEL-wOlO.js +1 -0
- package/dist/assets/desktop-BmXAJ9_W.js +1 -0
- package/dist/assets/diff-D97Zzqfu.js +1 -0
- package/dist/assets/docker-BcOcwvcX.js +1 -0
- package/dist/assets/dotenv-Da5cRb03.js +1 -0
- package/dist/assets/dracula-BzJJZx-M.js +1 -0
- package/dist/assets/dracula-soft-BXkSAIEj.js +1 -0
- package/dist/assets/dream-maker-BtqSS_iP.js +1 -0
- package/dist/assets/edge-BkV0erSs.js +1 -0
- package/dist/assets/elixir-CDX3lj18.js +1 -0
- package/dist/assets/elm-DbKCFpqz.js +1 -0
- package/dist/assets/emacs-lisp-C9XAeP06.js +1 -0
- package/dist/assets/erb-B12qg9BL.js +1 -0
- package/dist/assets/erlang-DsQrWhSR.js +1 -0
- package/dist/assets/everforest-dark-BgDCqdQA.js +1 -0
- package/dist/assets/everforest-light-C8M2exoo.js +1 -0
- package/dist/assets/fennel-BYunw83y.js +1 -0
- package/dist/assets/fish-BvzEVeQv.js +1 -0
- package/dist/assets/fluent-C4IJs8-o.js +1 -0
- package/dist/assets/fortran-fixed-form-CkoXwp7k.js +1 -0
- package/dist/assets/fortran-free-form-BxgE0vQu.js +1 -0
- package/dist/assets/fsharp-CXgrBDvD.js +1 -0
- package/dist/assets/gdresource-BOOCDP_w.js +1 -0
- package/dist/assets/gdscript-C5YyOfLZ.js +1 -0
- package/dist/assets/gdshader-DkwncUOv.js +1 -0
- package/dist/assets/genie-D0YGMca9.js +1 -0
- package/dist/assets/gherkin-DyxjwDmM.js +1 -0
- package/dist/assets/git-commit-F4YmCXRG.js +1 -0
- package/dist/assets/git-rebase-r7XF79zn.js +1 -0
- package/dist/assets/github-dark-DHJKELXO.js +1 -0
- package/dist/assets/github-dark-default-Cuk6v7N8.js +1 -0
- package/dist/assets/github-dark-dimmed-DH5Ifo-i.js +1 -0
- package/dist/assets/github-dark-high-contrast-E3gJ1_iC.js +1 -0
- package/dist/assets/github-light-DAi9KRSo.js +1 -0
- package/dist/assets/github-light-default-D7oLnXFd.js +1 -0
- package/dist/assets/github-light-high-contrast-BfjtVDDH.js +1 -0
- package/dist/assets/gleam-BspZqrRM.js +1 -0
- package/dist/assets/glimmer-js-Rg0-pVw9.js +1 -0
- package/dist/assets/glimmer-ts-U6CK756n.js +1 -0
- package/dist/assets/glsl-DplSGwfg.js +1 -0
- package/dist/assets/gn-n2N0HUVH.js +1 -0
- package/dist/assets/gnuplot-DdkO51Og.js +1 -0
- package/dist/assets/go-CxLEBnE3.js +1 -0
- package/dist/assets/graphql-ChdNCCLP.js +1 -0
- package/dist/assets/groovy-gcz8RCvz.js +1 -0
- package/dist/assets/gruvbox-dark-hard-CFHQjOhq.js +1 -0
- package/dist/assets/gruvbox-dark-medium-GsRaNv29.js +1 -0
- package/dist/assets/gruvbox-dark-soft-CVdnzihN.js +1 -0
- package/dist/assets/gruvbox-light-hard-CH1njM8p.js +1 -0
- package/dist/assets/gruvbox-light-medium-DRw_LuNl.js +1 -0
- package/dist/assets/gruvbox-light-soft-hJgmCMqR.js +1 -0
- package/dist/assets/hack-CaT9iCJl.js +1 -0
- package/dist/assets/haml-B8DHNrY2.js +1 -0
- package/dist/assets/handlebars-BL8al0AC.js +1 -0
- package/dist/assets/haskell-Df6bDoY_.js +1 -0
- package/dist/assets/haxe-CzTSHFRz.js +1 -0
- package/dist/assets/hcl-BWvSN4gD.js +1 -0
- package/dist/assets/hjson-D5-asLiD.js +1 -0
- package/dist/assets/hlsl-D3lLCCz7.js +1 -0
- package/dist/assets/horizon-BUw7H-hv.js +1 -0
- package/dist/assets/horizon-bright-Cn-bp-IR.js +1 -0
- package/dist/assets/houston-DnULxvSX.js +1 -0
- package/dist/assets/html-GMplVEZG.js +1 -0
- package/dist/assets/html-derivative-BFtXZ54Q.js +1 -0
- package/dist/assets/http-jrhK8wxY.js +1 -0
- package/dist/assets/hurl-irOxFIW8.js +1 -0
- package/dist/assets/hxml-Bvhsp5Yf.js +1 -0
- package/dist/assets/hy-DFXneXwc.js +1 -0
- package/dist/assets/imba-DGztddWO.js +1 -0
- package/dist/assets/index-B_lEiI-9.js +1544 -0
- package/dist/assets/index-CQT9NtoK.css +1 -0
- package/dist/assets/ini-BEwlwnbL.js +1 -0
- package/dist/assets/java-CylS5w8V.js +1 -0
- package/dist/assets/javascript-wDzz0qaB.js +1 -0
- package/dist/assets/jinja-4LBKfQ-Z.js +1 -0
- package/dist/assets/jison-wvAkD_A8.js +1 -0
- package/dist/assets/json-Cp-IABpG.js +1 -0
- package/dist/assets/json5-C9tS-k6U.js +1 -0
- package/dist/assets/jsonc-Des-eS-w.js +1 -0
- package/dist/assets/jsonl-DcaNXYhu.js +1 -0
- package/dist/assets/jsonnet-DFQXde-d.js +1 -0
- package/dist/assets/jssm-C2t-YnRu.js +1 -0
- package/dist/assets/jsx-g9-lgVsj.js +1 -0
- package/dist/assets/julia-CxzCAyBv.js +1 -0
- package/dist/assets/just-Cw27pwNe.js +1 -0
- package/dist/assets/kanagawa-dragon-CkXjmgJE.js +1 -0
- package/dist/assets/kanagawa-lotus-CfQXZHmo.js +1 -0
- package/dist/assets/kanagawa-wave-DWedfzmr.js +1 -0
- package/dist/assets/kdl-DV7GczEv.js +1 -0
- package/dist/assets/kotlin-BdnUsdx6.js +1 -0
- package/dist/assets/kusto-DZf3V79B.js +1 -0
- package/dist/assets/laserwave-DUszq2jm.js +1 -0
- package/dist/assets/latex-CWtU0Tv5.js +1 -0
- package/dist/assets/lean-BZvkOJ9d.js +1 -0
- package/dist/assets/less-B1dDrJ26.js +1 -0
- package/dist/assets/light-plus-B7mTdjB0.js +1 -0
- package/dist/assets/liquid-DYVedYrR.js +1 -0
- package/dist/assets/llvm-DjAJT7YJ.js +1 -0
- package/dist/assets/log-2UxHyX5q.js +1 -0
- package/dist/assets/logo-BtOb2qkB.js +1 -0
- package/dist/assets/lua-BaeVxFsk.js +1 -0
- package/dist/assets/luau-C-HG3fhB.js +1 -0
- package/dist/assets/make-CHLpvVh8.js +1 -0
- package/dist/assets/markdown-Cvjx9yec.js +1 -0
- package/dist/assets/marko-CnJfTvn9.js +1 -0
- package/dist/assets/material-theme-D5KoaKCx.js +1 -0
- package/dist/assets/material-theme-darker-BfHTSMKl.js +1 -0
- package/dist/assets/material-theme-lighter-B0m2ddpp.js +1 -0
- package/dist/assets/material-theme-ocean-CyktbL80.js +1 -0
- package/dist/assets/material-theme-palenight-Csfq5Kiy.js +1 -0
- package/dist/assets/matlab-D7o27uSR.js +1 -0
- package/dist/assets/mdc-BMNejdWA.js +1 -0
- package/dist/assets/mdx-Cmh6b_Ma.js +1 -0
- package/dist/assets/mermaid-mWjccvbQ.js +1 -0
- package/dist/assets/min-dark-CafNBF8u.js +1 -0
- package/dist/assets/min-light-CTRr51gU.js +1 -0
- package/dist/assets/mipsasm-CKIfxQSi.js +1 -0
- package/dist/assets/mojo-rZm6bMo-.js +1 -0
- package/dist/assets/monokai-D4h5O-jR.js +1 -0
- package/dist/assets/moonbit-_H4v1dQx.js +1 -0
- package/dist/assets/move-IF9eRakj.js +1 -0
- package/dist/assets/narrat-DRg8JJMk.js +1 -0
- package/dist/assets/nextflow-Zz6hmt5N.js +1 -0
- package/dist/assets/nextflow-groovy-BeH2EWoN.js +1 -0
- package/dist/assets/nginx-BpAMiNFr.js +1 -0
- package/dist/assets/night-owl-C39BiMTA.js +1 -0
- package/dist/assets/night-owl-light-CMTm3GFP.js +1 -0
- package/dist/assets/nim-CVrawwO9.js +1 -0
- package/dist/assets/nix-CwoSXNpI.js +1 -0
- package/dist/assets/nord-Ddv68eIx.js +1 -0
- package/dist/assets/nushell-Cz2AlsmD.js +1 -0
- package/dist/assets/objective-c-DXmwc3jG.js +1 -0
- package/dist/assets/objective-cpp-CLxacb5B.js +1 -0
- package/dist/assets/ocaml-C0hk2d4L.js +1 -0
- package/dist/assets/odin-BBf5iR-q.js +1 -0
- package/dist/assets/one-dark-pro-DVMEJ2y_.js +1 -0
- package/dist/assets/one-light-C3Wv6jpd.js +1 -0
- package/dist/assets/openscad-C4EeE6gA.js +1 -0
- package/dist/assets/pascal-D93ZcfNL.js +1 -0
- package/dist/assets/perl-C0TMdlhV.js +1 -0
- package/dist/assets/php-Dhbhpdrm.js +1 -0
- package/dist/assets/pkl-u5AG7uiY.js +1 -0
- package/dist/assets/plastic-3e1v2bzS.js +1 -0
- package/dist/assets/plsql-ChMvpjG-.js +1 -0
- package/dist/assets/po-BTJTHyun.js +1 -0
- package/dist/assets/poimandres-CS3Unz2-.js +1 -0
- package/dist/assets/polar-C0HS_06l.js +1 -0
- package/dist/assets/postcss-CXtECtnM.js +1 -0
- package/dist/assets/powerquery-CEu0bR-o.js +1 -0
- package/dist/assets/powershell-Dpen1YoG.js +1 -0
- package/dist/assets/prisma-Dd19v3D-.js +1 -0
- package/dist/assets/prolog-CbFg5uaA.js +1 -0
- package/dist/assets/proto-C7zT0LnQ.js +1 -0
- package/dist/assets/pug-CGlum2m_.js +1 -0
- package/dist/assets/puppet-BMWR74SV.js +1 -0
- package/dist/assets/purescript-CklMAg4u.js +1 -0
- package/dist/assets/python-B6aJPvgy.js +1 -0
- package/dist/assets/qml-3beO22l8.js +1 -0
- package/dist/assets/qmldir-C8lEn-DE.js +1 -0
- package/dist/assets/qss-IeuSbFQv.js +1 -0
- package/dist/assets/r-Dspwwk_N.js +1 -0
- package/dist/assets/racket-BqYA7rlc.js +1 -0
- package/dist/assets/raku-DXvB9xmW.js +1 -0
- package/dist/assets/razor-Uh8Bk_45.js +1 -0
- package/dist/assets/red-bN70gL4F.js +1 -0
- package/dist/assets/reg-C-SQnVFl.js +1 -0
- package/dist/assets/regexp-CDVJQ6XC.js +1 -0
- package/dist/assets/rel-C3B-1QV4.js +1 -0
- package/dist/assets/riscv-BM1_JUlF.js +1 -0
- package/dist/assets/ron-D8l8udqQ.js +1 -0
- package/dist/assets/rose-pine-dawn-DHQR4-dF.js +1 -0
- package/dist/assets/rose-pine-moon-D4_iv3hh.js +1 -0
- package/dist/assets/rose-pine-qdsjHGoJ.js +1 -0
- package/dist/assets/rosmsg-BJDFO7_C.js +1 -0
- package/dist/assets/rst-BrH8l1NY.js +1 -0
- package/dist/assets/ruby-Dw2BHqvy.js +1 -0
- package/dist/assets/rust-B1yitclQ.js +1 -0
- package/dist/assets/sas-cz2c8ADy.js +1 -0
- package/dist/assets/sass-Cj5Yp3dK.js +1 -0
- package/dist/assets/scala-C151Ov-r.js +1 -0
- package/dist/assets/scheme-C98Dy4si.js +1 -0
- package/dist/assets/scss-OYdSNvt2.js +1 -0
- package/dist/assets/sdbl-DVxCFoDh.js +1 -0
- package/dist/assets/shaderlab-Dg9Lc6iA.js +1 -0
- package/dist/assets/shellscript-Yzrsuije.js +1 -0
- package/dist/assets/shellsession-BADoaaVG.js +1 -0
- package/dist/assets/slack-dark-BthQWCQV.js +1 -0
- package/dist/assets/slack-ochin-DqwNpetd.js +1 -0
- package/dist/assets/smalltalk-BERRCDM3.js +1 -0
- package/dist/assets/snazzy-light-Bw305WKR.js +1 -0
- package/dist/assets/solarized-dark-DXbdFlpD.js +1 -0
- package/dist/assets/solarized-light-L9t79GZl.js +1 -0
- package/dist/assets/solidity-rGO070M0.js +1 -0
- package/dist/assets/soy-Brmx7dQM.js +1 -0
- package/dist/assets/sparql-rVzFXLq3.js +1 -0
- package/dist/assets/splunk-BtCnVYZw.js +1 -0
- package/dist/assets/sql-BLtJtn59.js +1 -0
- package/dist/assets/ssh-config-_ykCGR6B.js +1 -0
- package/dist/assets/stata-BH5u7GGu.js +1 -0
- package/dist/assets/stylus-BEDo0Tqx.js +1 -0
- package/dist/assets/surrealql-Bq5Q-fJD.js +1 -0
- package/dist/assets/svelte-C_ipcX3V.js +1 -0
- package/dist/assets/swift-D82vCrfD.js +1 -0
- package/dist/assets/synthwave-84-CbfX1IO0.js +1 -0
- package/dist/assets/system-verilog-CnnmHF94.js +1 -0
- package/dist/assets/systemd-4A_iFExJ.js +1 -0
- package/dist/assets/talonscript-CkByrt1z.js +1 -0
- package/dist/assets/tasl-QIJgUcNo.js +1 -0
- package/dist/assets/tcl-dwOrl1Do.js +1 -0
- package/dist/assets/templ-P3uqSqPl.js +1 -0
- package/dist/assets/terraform-BETggiCN.js +1 -0
- package/dist/assets/tex-idrVyKtj.js +1 -0
- package/dist/assets/tokyo-night-hegEt444.js +1 -0
- package/dist/assets/toml-vGWfd6FD.js +1 -0
- package/dist/assets/ts-tags-zn1MmPIZ.js +1 -0
- package/dist/assets/tsv-B_m7g4N7.js +1 -0
- package/dist/assets/tsx-COt5Ahok.js +1 -0
- package/dist/assets/turtle-BsS91CYL.js +1 -0
- package/dist/assets/twig-DNn4PbVi.js +1 -0
- package/dist/assets/typescript-BPQ3VLAy.js +1 -0
- package/dist/assets/typespec-BGHnOYBU.js +1 -0
- package/dist/assets/typst-DHCkPAjA.js +1 -0
- package/dist/assets/v-BcVCzyr7.js +1 -0
- package/dist/assets/vala-CsfeWuGM.js +1 -0
- package/dist/assets/vb-D17OF-Vu.js +1 -0
- package/dist/assets/verilog-BQ8w6xss.js +1 -0
- package/dist/assets/vesper-DU1UobuO.js +1 -0
- package/dist/assets/vhdl-CeAyd5Ju.js +1 -0
- package/dist/assets/viml-CJc9bBzg.js +1 -0
- package/dist/assets/vitesse-black-Bkuqu6BP.js +1 -0
- package/dist/assets/vitesse-dark-D0r3Knsf.js +1 -0
- package/dist/assets/vitesse-light-CVO1_9PV.js +1 -0
- package/dist/assets/vue-DN_0RTcg.js +1 -0
- package/dist/assets/vue-html-AaS7Mt5G.js +1 -0
- package/dist/assets/vue-vine-CQOfvN7w.js +1 -0
- package/dist/assets/vyper-CDx5xZoG.js +1 -0
- package/dist/assets/wasm-CG6Dc4jp.js +1 -0
- package/dist/assets/wasm-MzD3tlZU.js +1 -0
- package/dist/assets/wenyan-BV7otONQ.js +1 -0
- package/dist/assets/wgsl-Dx-B1_4e.js +1 -0
- package/dist/assets/wikitext-BhOHFoWU.js +1 -0
- package/dist/assets/wit-5i3qLPDT.js +1 -0
- package/dist/assets/wolfram-lXgVvXCa.js +1 -0
- package/dist/assets/xml-sdJ4AIDG.js +1 -0
- package/dist/assets/xsl-CtQFsRM5.js +1 -0
- package/dist/assets/yaml-Buea-lGh.js +1 -0
- package/dist/assets/zenscript-DVFEvuxE.js +1 -0
- package/dist/assets/zig-VOosw3JB.js +1 -0
- package/dist/index.html +18 -0
- package/index.html +17 -0
- package/package.json +54 -0
- package/postcss.config.js +6 -0
- package/scripts/start-dev.ts +68 -0
- package/src/App.tsx +7 -0
- package/src/components/WorkspaceSwitcher.tsx +125 -0
- package/src/components/ui/avatar.tsx +47 -0
- package/src/components/ui/badge.tsx +35 -0
- package/src/components/ui/button.tsx +55 -0
- package/src/components/ui/card.tsx +85 -0
- package/src/components/ui/collapsible.tsx +9 -0
- package/src/components/ui/dialog.tsx +60 -0
- package/src/components/ui/input.tsx +24 -0
- package/src/components/ui/scroll-area.tsx +45 -0
- package/src/index.css +190 -0
- package/src/lib/utils.ts +6 -0
- package/src/lib/workspace-vfs.ts +190 -0
- package/src/main.tsx +10 -0
- package/src/pages/ChatPage.tsx +1098 -0
- package/tailwind.config.js +73 -0
- package/tsconfig.json +22 -0
- package/vite.config.ts +18 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { X } from 'lucide-react';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
interface DialogProps {
|
|
5
|
+
open: boolean;
|
|
6
|
+
onOpenChange: (open: boolean) => void;
|
|
7
|
+
children: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function Dialog({ open, onOpenChange, children }: DialogProps) {
|
|
11
|
+
React.useEffect(() => {
|
|
12
|
+
const handleEscape = (e: KeyboardEvent) => {
|
|
13
|
+
if (e.key === 'Escape') onOpenChange(false);
|
|
14
|
+
};
|
|
15
|
+
if (open) document.addEventListener('keydown', handleEscape);
|
|
16
|
+
return () => document.removeEventListener('keydown', handleEscape);
|
|
17
|
+
}, [open, onOpenChange]);
|
|
18
|
+
|
|
19
|
+
if (!open) return null;
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
|
23
|
+
<div
|
|
24
|
+
className="fixed inset-0 bg-black/50"
|
|
25
|
+
onClick={() => onOpenChange(false)}
|
|
26
|
+
/>
|
|
27
|
+
<div className="relative z-50 w-full max-w-2xl max-h-[85vh] overflow-hidden rounded-lg border bg-background shadow-lg">
|
|
28
|
+
{children}
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function DialogHeader({ children, className = '' }: { children: React.ReactNode; className?: string }) {
|
|
35
|
+
return (
|
|
36
|
+
<div className={`flex items-center justify-between p-4 border-b ${className}`}>
|
|
37
|
+
{children}
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function DialogTitle({ children }: { children: React.ReactNode }) {
|
|
43
|
+
return <h2 className="text-lg font-semibold">{children}</h2>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function DialogContent({ children, className = '' }: { children: React.ReactNode; className?: string }) {
|
|
47
|
+
return <div className={`p-4 overflow-auto max-h-[calc(85vh-4rem)] ${className}`}>{children}</div>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function DialogClose({ onClose }: { onClose: () => void }) {
|
|
51
|
+
return (
|
|
52
|
+
<button
|
|
53
|
+
onClick={onClose}
|
|
54
|
+
className="rounded-sm opacity-70 hover:opacity-100 transition-opacity"
|
|
55
|
+
>
|
|
56
|
+
<X className="h-4 w-4" />
|
|
57
|
+
<span className="sr-only">Close</span>
|
|
58
|
+
</button>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { cn } from '@/lib/utils';
|
|
3
|
+
|
|
4
|
+
export interface InputProps
|
|
5
|
+
extends React.InputHTMLAttributes<HTMLInputElement> {}
|
|
6
|
+
|
|
7
|
+
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
8
|
+
({ className, type, ...props }, ref) => {
|
|
9
|
+
return (
|
|
10
|
+
<input
|
|
11
|
+
type={type}
|
|
12
|
+
className={cn(
|
|
13
|
+
'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50',
|
|
14
|
+
className,
|
|
15
|
+
)}
|
|
16
|
+
ref={ref}
|
|
17
|
+
{...props}
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
},
|
|
21
|
+
);
|
|
22
|
+
Input.displayName = 'Input';
|
|
23
|
+
|
|
24
|
+
export { Input };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { cn } from '@/lib/utils';
|
|
4
|
+
|
|
5
|
+
const ScrollArea = React.forwardRef<
|
|
6
|
+
React.ElementRef<typeof ScrollAreaPrimitive.Root>,
|
|
7
|
+
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.Root>
|
|
8
|
+
>(({ className, children, ...props }, ref) => (
|
|
9
|
+
<ScrollAreaPrimitive.Root
|
|
10
|
+
ref={ref}
|
|
11
|
+
className={cn('relative overflow-hidden', className)}
|
|
12
|
+
{...props}
|
|
13
|
+
>
|
|
14
|
+
<ScrollAreaPrimitive.Viewport className="h-full w-full rounded-[inherit]">
|
|
15
|
+
{children}
|
|
16
|
+
</ScrollAreaPrimitive.Viewport>
|
|
17
|
+
<ScrollBar />
|
|
18
|
+
<ScrollAreaPrimitive.Corner />
|
|
19
|
+
</ScrollAreaPrimitive.Root>
|
|
20
|
+
));
|
|
21
|
+
ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
|
|
22
|
+
|
|
23
|
+
const ScrollBar = React.forwardRef<
|
|
24
|
+
React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
|
|
25
|
+
React.ComponentPropsWithoutRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>
|
|
26
|
+
>(({ className, orientation = 'vertical', ...props }, ref) => (
|
|
27
|
+
<ScrollAreaPrimitive.ScrollAreaScrollbar
|
|
28
|
+
ref={ref}
|
|
29
|
+
orientation={orientation}
|
|
30
|
+
className={cn(
|
|
31
|
+
'flex touch-none select-none transition-colors',
|
|
32
|
+
orientation === 'vertical' &&
|
|
33
|
+
'h-full w-2.5 border-l border-l-transparent p-[1px]',
|
|
34
|
+
orientation === 'horizontal' &&
|
|
35
|
+
'h-2.5 flex-col border-t border-t-transparent p-[1px]',
|
|
36
|
+
className,
|
|
37
|
+
)}
|
|
38
|
+
{...props}
|
|
39
|
+
>
|
|
40
|
+
<ScrollAreaPrimitive.ScrollAreaThumb className="relative flex-1 rounded-full bg-border" />
|
|
41
|
+
</ScrollAreaPrimitive.ScrollAreaScrollbar>
|
|
42
|
+
));
|
|
43
|
+
ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
|
|
44
|
+
|
|
45
|
+
export { ScrollArea, ScrollBar };
|
package/src/index.css
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
@tailwind base;
|
|
2
|
+
@tailwind components;
|
|
3
|
+
@tailwind utilities;
|
|
4
|
+
|
|
5
|
+
@layer base {
|
|
6
|
+
:root {
|
|
7
|
+
--background: 0 0% 100%;
|
|
8
|
+
--foreground: 222.2 84% 4.9%;
|
|
9
|
+
--card: 0 0% 100%;
|
|
10
|
+
--card-foreground: 222.2 84% 4.9%;
|
|
11
|
+
--popover: 0 0% 100%;
|
|
12
|
+
--popover-foreground: 222.2 84% 4.9%;
|
|
13
|
+
--primary: 222.2 47.4% 11.2%;
|
|
14
|
+
--primary-foreground: 210 40% 98%;
|
|
15
|
+
--secondary: 210 40% 96.1%;
|
|
16
|
+
--secondary-foreground: 222.2 47.4% 11.2%;
|
|
17
|
+
--muted: 210 40% 96.1%;
|
|
18
|
+
--muted-foreground: 215.4 16.3% 46.9%;
|
|
19
|
+
--accent: 210 40% 96.1%;
|
|
20
|
+
--accent-foreground: 222.2 47.4% 11.2%;
|
|
21
|
+
--destructive: 0 84.2% 60.2%;
|
|
22
|
+
--destructive-foreground: 210 40% 98%;
|
|
23
|
+
--border: 214.3 31.8% 91.4%;
|
|
24
|
+
--input: 214.3 31.8% 91.4%;
|
|
25
|
+
--ring: 222.2 84% 4.9%;
|
|
26
|
+
--radius: 0.5rem;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* .dark {
|
|
30
|
+
--background: 222.2 84% 4.9%;
|
|
31
|
+
--foreground: 210 40% 98%;
|
|
32
|
+
--card: 222.2 84% 4.9%;
|
|
33
|
+
--card-foreground: 210 40% 98%;
|
|
34
|
+
--popover: 222.2 84% 4.9%;
|
|
35
|
+
--popover-foreground: 210 40% 98%;
|
|
36
|
+
--primary: 210 40% 98%;
|
|
37
|
+
--primary-foreground: 222.2 47.4% 11.2%;
|
|
38
|
+
--secondary: 217.2 32.6% 17.5%;
|
|
39
|
+
--secondary-foreground: 210 40% 98%;
|
|
40
|
+
--muted: 217.2 32.6% 17.5%;
|
|
41
|
+
--muted-foreground: 215 20.2% 65.1%;
|
|
42
|
+
--accent: 217.2 32.6% 17.5%;
|
|
43
|
+
--accent-foreground: 210 40% 98%;
|
|
44
|
+
--destructive: 0 62.8% 30.6%;
|
|
45
|
+
--destructive-foreground: 210 40% 98%;
|
|
46
|
+
--border: 217.2 32.6% 17.5%;
|
|
47
|
+
--input: 217.2 32.6% 17.5%;
|
|
48
|
+
--ring: 212.7 26.8% 83.9%;
|
|
49
|
+
} */
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@layer base {
|
|
53
|
+
* {
|
|
54
|
+
@apply border-border;
|
|
55
|
+
}
|
|
56
|
+
body {
|
|
57
|
+
@apply bg-background text-foreground;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* Tiptap Markdown Editor Styles */
|
|
62
|
+
.markdown-editor .tiptap {
|
|
63
|
+
outline: none;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.markdown-editor .tiptap p {
|
|
67
|
+
margin: 0;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.markdown-editor .tiptap > * + * {
|
|
71
|
+
margin-top: 0.5em;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* Placeholder styling */
|
|
75
|
+
.markdown-editor .tiptap p.is-editor-empty:first-child::before {
|
|
76
|
+
color: hsl(var(--muted-foreground));
|
|
77
|
+
content: attr(data-placeholder);
|
|
78
|
+
float: left;
|
|
79
|
+
height: 0;
|
|
80
|
+
pointer-events: none;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* Inline code */
|
|
84
|
+
.markdown-editor .tiptap code {
|
|
85
|
+
background-color: hsl(var(--muted));
|
|
86
|
+
border-radius: 0.25rem;
|
|
87
|
+
padding: 0.125rem 0.25rem;
|
|
88
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
89
|
+
font-size: 0.875em;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/* Code blocks */
|
|
93
|
+
.markdown-editor .tiptap pre {
|
|
94
|
+
background-color: hsl(var(--muted));
|
|
95
|
+
border-radius: 0.375rem;
|
|
96
|
+
padding: 0.5rem 0.75rem;
|
|
97
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
98
|
+
font-size: 0.875em;
|
|
99
|
+
overflow-x: auto;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.markdown-editor .tiptap pre code {
|
|
103
|
+
background: none;
|
|
104
|
+
padding: 0;
|
|
105
|
+
font-size: inherit;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/* Blockquotes */
|
|
109
|
+
.markdown-editor .tiptap blockquote {
|
|
110
|
+
border-left: 4px solid hsl(var(--muted-foreground) / 0.3);
|
|
111
|
+
padding-left: 1rem;
|
|
112
|
+
font-style: italic;
|
|
113
|
+
color: hsl(var(--muted-foreground));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* Lists */
|
|
117
|
+
.markdown-editor .tiptap ul,
|
|
118
|
+
.markdown-editor .tiptap ol {
|
|
119
|
+
padding-left: 1.5rem;
|
|
120
|
+
margin: 0.25em 0;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.markdown-editor .tiptap ul {
|
|
124
|
+
list-style-type: disc;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.markdown-editor .tiptap ol {
|
|
128
|
+
list-style-type: decimal;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.markdown-editor .tiptap li {
|
|
132
|
+
margin: 0.125em 0;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* Headings - more subtle for chat input */
|
|
136
|
+
.markdown-editor .tiptap h1,
|
|
137
|
+
.markdown-editor .tiptap h2,
|
|
138
|
+
.markdown-editor .tiptap h3 {
|
|
139
|
+
font-weight: 600;
|
|
140
|
+
line-height: 1.25;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.markdown-editor .tiptap h1 {
|
|
144
|
+
font-size: 1.25em;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.markdown-editor .tiptap h2 {
|
|
148
|
+
font-size: 1.125em;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.markdown-editor .tiptap h3 {
|
|
152
|
+
font-size: 1em;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/* Bold & Italic */
|
|
156
|
+
.markdown-editor .tiptap strong {
|
|
157
|
+
font-weight: 600;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.markdown-editor .tiptap em {
|
|
161
|
+
font-style: italic;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/* Strikethrough */
|
|
165
|
+
.markdown-editor .tiptap s {
|
|
166
|
+
text-decoration: line-through;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* Code block wrapper with language input */
|
|
170
|
+
.markdown-editor .code-block-wrapper {
|
|
171
|
+
display: flex;
|
|
172
|
+
flex-direction: column;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.markdown-editor .code-block-wrapper pre {
|
|
176
|
+
margin: 0;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.markdown-editor .code-block-wrapper .language-input-wrapper {
|
|
180
|
+
user-select: none;
|
|
181
|
+
pointer-events: auto;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.markdown-editor .code-block-wrapper .language-input {
|
|
185
|
+
background: transparent;
|
|
186
|
+
user-select: text !important;
|
|
187
|
+
pointer-events: auto !important;
|
|
188
|
+
cursor: text;
|
|
189
|
+
-webkit-user-select: text !important;
|
|
190
|
+
}
|
package/src/lib/utils.ts
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HttpBackend,
|
|
3
|
+
VFSStore,
|
|
4
|
+
resolveEntry,
|
|
5
|
+
type VirtualFile,
|
|
6
|
+
type VirtualProject,
|
|
7
|
+
type WatchCallback,
|
|
8
|
+
} from '@aprovan/patchwork-compiler';
|
|
9
|
+
|
|
10
|
+
const VFS_BASE_URL = '/vfs';
|
|
11
|
+
|
|
12
|
+
let storeInstance: VFSStore | null = null;
|
|
13
|
+
|
|
14
|
+
function getStore(): VFSStore {
|
|
15
|
+
if (!storeInstance) {
|
|
16
|
+
const backend = new HttpBackend({ baseUrl: VFS_BASE_URL });
|
|
17
|
+
storeInstance = new VFSStore(backend, {
|
|
18
|
+
sync: false,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
return storeInstance;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/** Tear down the current VFS store instance so the next call to getStore() creates a fresh one. */
|
|
25
|
+
export function resetStore(): void {
|
|
26
|
+
storeInstance = null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function normalizePath(path: string): string {
|
|
30
|
+
return path.replace(/^\/+|\/+$/g, '');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function dirname(path: string): string {
|
|
34
|
+
const normalized = normalizePath(path);
|
|
35
|
+
if (!normalized || !normalized.includes('/')) return '';
|
|
36
|
+
return normalized.split('/').slice(0, -1).join('/');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function basename(path: string): string {
|
|
40
|
+
const normalized = normalizePath(path);
|
|
41
|
+
if (!normalized) return '';
|
|
42
|
+
const parts = normalized.split('/');
|
|
43
|
+
return parts[parts.length - 1] ?? '';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function joinPath(base: string, path: string): string {
|
|
47
|
+
const normalizedBase = normalizePath(base);
|
|
48
|
+
const normalizedPath = normalizePath(path);
|
|
49
|
+
if (!normalizedBase) return normalizedPath;
|
|
50
|
+
if (!normalizedPath) return normalizedBase;
|
|
51
|
+
return `${normalizedBase}/${normalizedPath}`;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function toPrefix(path: string): string {
|
|
55
|
+
const normalized = normalizePath(path);
|
|
56
|
+
return normalized ? `${normalized}/` : '';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function toWorkspaceTreeFiles(paths: string[]): VirtualFile[] {
|
|
60
|
+
return paths.map((path) => ({ path, content: '' }));
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function toProjectRelativePath(projectId: string, absolutePath: string): string {
|
|
64
|
+
if (!projectId) return normalizePath(absolutePath);
|
|
65
|
+
const normalizedProjectId = normalizePath(projectId);
|
|
66
|
+
const normalizedPath = normalizePath(absolutePath);
|
|
67
|
+
const prefix = `${normalizedProjectId}/`;
|
|
68
|
+
if (normalizedPath.startsWith(prefix)) {
|
|
69
|
+
return normalizedPath.slice(prefix.length);
|
|
70
|
+
}
|
|
71
|
+
return normalizedPath;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function toWorkspacePath(projectId: string, relativePath: string): string {
|
|
75
|
+
const normalizedProjectId = normalizePath(projectId);
|
|
76
|
+
const normalizedRelativePath = normalizePath(relativePath);
|
|
77
|
+
if (!normalizedProjectId) return normalizedRelativePath;
|
|
78
|
+
return joinPath(normalizedProjectId, normalizedRelativePath);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface WorkspaceEntry {
|
|
82
|
+
name: string;
|
|
83
|
+
path: string;
|
|
84
|
+
isDir: boolean;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export async function listWorkspaceEntries(path = ''): Promise<WorkspaceEntry[]> {
|
|
88
|
+
const store = getStore();
|
|
89
|
+
const normalized = normalizePath(path);
|
|
90
|
+
const entries = await store.readdir(normalized);
|
|
91
|
+
|
|
92
|
+
return entries
|
|
93
|
+
.map((entry) => ({
|
|
94
|
+
name: entry.name,
|
|
95
|
+
path: normalized ? `${normalized}/${entry.name}` : entry.name,
|
|
96
|
+
isDir: entry.isDirectory(),
|
|
97
|
+
}))
|
|
98
|
+
.sort((a, b) => {
|
|
99
|
+
if (a.isDir !== b.isDir) return a.isDir ? -1 : 1;
|
|
100
|
+
return a.name.localeCompare(b.name);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export async function listWorkspacePaths(): Promise<string[]> {
|
|
105
|
+
return getStore().listFiles();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export async function loadWorkspaceDirectoryProject(
|
|
109
|
+
directoryPath: string,
|
|
110
|
+
): Promise<VirtualProject | null> {
|
|
111
|
+
const store = getStore();
|
|
112
|
+
const normalized = normalizePath(directoryPath);
|
|
113
|
+
const prefix = toPrefix(normalized);
|
|
114
|
+
const allPaths = await store.listFiles(normalized);
|
|
115
|
+
const filePaths = allPaths.filter((path) =>
|
|
116
|
+
prefix ? path.startsWith(prefix) : true,
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
if (filePaths.length === 0) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const files = new Map<string, VirtualFile>();
|
|
124
|
+
await Promise.all(
|
|
125
|
+
filePaths.map(async (path) => {
|
|
126
|
+
const content = await store.readFile(path);
|
|
127
|
+
const relativePath = toProjectRelativePath(normalized, path);
|
|
128
|
+
files.set(relativePath, { path: relativePath, content });
|
|
129
|
+
}),
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
id: normalized,
|
|
134
|
+
entry: resolveEntry(files),
|
|
135
|
+
files,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export async function loadWorkspaceFileProject(
|
|
140
|
+
filePath: string,
|
|
141
|
+
): Promise<VirtualProject | null> {
|
|
142
|
+
const store = getStore();
|
|
143
|
+
const normalized = normalizePath(filePath);
|
|
144
|
+
const fileName = basename(normalized);
|
|
145
|
+
const projectId = dirname(normalized);
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
const content = await store.readFile(normalized);
|
|
149
|
+
return {
|
|
150
|
+
id: projectId,
|
|
151
|
+
entry: fileName,
|
|
152
|
+
files: new Map([[fileName, { path: fileName, content }]]),
|
|
153
|
+
};
|
|
154
|
+
} catch {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function createSingleWorkspaceFileProject(
|
|
160
|
+
filePath: string,
|
|
161
|
+
content: string,
|
|
162
|
+
): VirtualProject {
|
|
163
|
+
const normalized = normalizePath(filePath);
|
|
164
|
+
const fileName = basename(normalized);
|
|
165
|
+
const projectId = dirname(normalized);
|
|
166
|
+
const files = new Map<string, VirtualFile>([
|
|
167
|
+
[fileName, { path: fileName, content }],
|
|
168
|
+
]);
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
id: projectId,
|
|
172
|
+
entry: fileName,
|
|
173
|
+
files,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export async function saveWorkspaceProject(
|
|
178
|
+
project: VirtualProject,
|
|
179
|
+
): Promise<void> {
|
|
180
|
+
const store = getStore();
|
|
181
|
+
await Promise.all(
|
|
182
|
+
Array.from(project.files.values()).map((file) =>
|
|
183
|
+
store.writeFile(toWorkspacePath(project.id, file.path), file.content),
|
|
184
|
+
),
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
export function subscribeToWorkspaceChanges(callback: WatchCallback): () => void {
|
|
189
|
+
return getStore().watch('', callback);
|
|
190
|
+
}
|
package/src/main.tsx
ADDED