@hienlh/ppm 0.13.44 → 0.13.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -0
- package/assets/skills/ppm/SKILL.md +1 -1
- package/assets/skills/ppm/references/http-api.md +1 -1
- package/dist/web/assets/ai-settings-section-Btix996C.js +2 -1
- package/dist/web/assets/ai-settings-section-Btix996C.js.map +1 -0
- package/dist/web/assets/api-client-DIhJ5qVW.js +2 -1
- package/dist/web/assets/api-client-DIhJ5qVW.js.map +1 -0
- package/dist/web/assets/api-settings-DnHv6JgF.js +2 -1
- package/dist/web/assets/api-settings-DnHv6JgF.js.map +1 -0
- package/dist/web/assets/arrow-up-Rcw6_KKu.js +2 -1
- package/dist/web/assets/arrow-up-Rcw6_KKu.js.map +1 -0
- package/dist/web/assets/audio-preview-B6a1Djtr.js +2 -1
- package/dist/web/assets/audio-preview-B6a1Djtr.js.map +1 -0
- package/dist/web/assets/chat-tab-Z5VNzYCz.js +2 -1
- package/dist/web/assets/chat-tab-Z5VNzYCz.js.map +1 -0
- package/dist/web/assets/chevron-right-DnHIvvcy.js +2 -1
- package/dist/web/assets/chevron-right-DnHIvvcy.js.map +1 -0
- package/dist/web/assets/code-DGBecc50.js +2 -1
- package/dist/web/assets/code-DGBecc50.js.map +1 -0
- package/dist/web/assets/code-editor-Clvs0e0Q.js +2 -1
- package/dist/web/assets/code-editor-Clvs0e0Q.js.map +1 -0
- package/dist/web/assets/conflict-editor-B6nO1gln.js +2 -1
- package/dist/web/assets/conflict-editor-B6nO1gln.js.map +1 -0
- package/dist/web/assets/createLucideIcon-BjHrJDVb.js +2 -1
- package/dist/web/assets/createLucideIcon-BjHrJDVb.js.map +1 -0
- package/dist/web/assets/csv-parser-Dly5nqE1.js +2 -1
- package/dist/web/assets/csv-parser-Dly5nqE1.js.map +1 -0
- package/dist/web/assets/csv-preview-CsqFmPzb.js +2 -1
- package/dist/web/assets/csv-preview-CsqFmPzb.js.map +1 -0
- package/dist/web/assets/data-grid-overlay-editor-aTzJjALy.js +2 -1
- package/dist/web/assets/data-grid-overlay-editor-aTzJjALy.js.map +1 -0
- package/dist/web/assets/data-grid-types-BISkUXAY.js +2 -1
- package/dist/web/assets/data-grid-types-BISkUXAY.js.map +1 -0
- package/dist/web/assets/database-DOWH9-Vv.js +2 -1
- package/dist/web/assets/database-DOWH9-Vv.js.map +1 -0
- package/dist/web/assets/database-viewer-Boup8MJ_.js +2 -1
- package/dist/web/assets/database-viewer-Boup8MJ_.js.map +1 -0
- package/dist/web/assets/diff-viewer-Je2KYGME.js +2 -1
- package/dist/web/assets/diff-viewer-Je2KYGME.js.map +1 -0
- package/dist/web/assets/dist-B1I_4Jtc.js +2 -1
- package/dist/web/assets/dist-B1I_4Jtc.js.map +1 -0
- package/dist/web/assets/dist-CcDNqGjt.js +2 -1
- package/dist/web/assets/dist-CcDNqGjt.js.map +1 -0
- package/dist/web/assets/dist-wf2npcsG.js +2 -1
- package/dist/web/assets/dist-wf2npcsG.js.map +1 -0
- package/dist/web/assets/esm-UZtw2QcY.js +2 -1
- package/dist/web/assets/esm-UZtw2QcY.js.map +1 -0
- package/dist/web/assets/extension-webview-T9TN70nb.js +2 -1
- package/dist/web/assets/extension-webview-T9TN70nb.js.map +1 -0
- package/dist/web/assets/file-exclamation-point-BwzaQ50n.js +2 -1
- package/dist/web/assets/file-exclamation-point-BwzaQ50n.js.map +1 -0
- package/dist/web/assets/file-store-DOxcU_7s.js +2 -1
- package/dist/web/assets/file-store-DOxcU_7s.js.map +1 -0
- package/dist/web/assets/glide-data-grid-CqT8WzTs.js +2 -1
- package/dist/web/assets/glide-data-grid-CqT8WzTs.js.map +1 -0
- package/dist/web/assets/image-preview-DeNUcGI9.js +2 -1
- package/dist/web/assets/image-preview-DeNUcGI9.js.map +1 -0
- package/dist/web/assets/index-DJtqbPFT.js +2 -1
- package/dist/web/assets/index-DJtqbPFT.js.map +1 -0
- package/dist/web/assets/input-_LFQwhzd.js +2 -1
- package/dist/web/assets/input-_LFQwhzd.js.map +1 -0
- package/dist/web/assets/katex-Bqvo_ZG0.js +2 -1
- package/dist/web/assets/katex-Bqvo_ZG0.js.map +1 -0
- package/dist/web/assets/lib-Bu71-TFS.js +2 -1
- package/dist/web/assets/lib-Bu71-TFS.js.map +1 -0
- package/dist/web/assets/markdown-renderer-CXPtICSx.js +2 -1
- package/dist/web/assets/markdown-renderer-CXPtICSx.js.map +1 -0
- package/dist/web/assets/number-overlay-editor-CewUR5pB.js +2 -1
- package/dist/web/assets/number-overlay-editor-CewUR5pB.js.map +1 -0
- package/dist/web/assets/pdf-preview-DI2JU2Lm.js +2 -1
- package/dist/web/assets/pdf-preview-DI2JU2Lm.js.map +1 -0
- package/dist/web/assets/port-forwarding-tab-Cuv_37LW.js +2 -1
- package/dist/web/assets/port-forwarding-tab-Cuv_37LW.js.map +1 -0
- package/dist/web/assets/postgres-viewer-D76ygOZo.js +2 -1
- package/dist/web/assets/postgres-viewer-D76ygOZo.js.map +1 -0
- package/dist/web/assets/react-DMIOAtcX.js +2 -1
- package/dist/web/assets/react-DMIOAtcX.js.map +1 -0
- package/dist/web/assets/refresh-cw-BjrAbUJe.js +2 -1
- package/dist/web/assets/refresh-cw-BjrAbUJe.js.map +1 -0
- package/dist/web/assets/scroll-area-BDi_FNzr.js +2 -1
- package/dist/web/assets/scroll-area-BDi_FNzr.js.map +1 -0
- package/dist/web/assets/search-tM8K5zWU.js +2 -1
- package/dist/web/assets/search-tM8K5zWU.js.map +1 -0
- package/dist/web/assets/settings-store-CVrIYYCB.js +2 -1
- package/dist/web/assets/settings-store-CVrIYYCB.js.map +1 -0
- package/dist/web/assets/sparkles-CulWHe4c.js +2 -1
- package/dist/web/assets/sparkles-CulWHe4c.js.map +1 -0
- package/dist/web/assets/sql-query-editor-lSlKMPlG.js +2 -1
- package/dist/web/assets/sql-query-editor-lSlKMPlG.js.map +1 -0
- package/dist/web/assets/sqlite-viewer-DwTatNwI.js +2 -1
- package/dist/web/assets/sqlite-viewer-DwTatNwI.js.map +1 -0
- package/dist/web/assets/tab-store-S9w6U5gm.js +2 -1
- package/dist/web/assets/tab-store-S9w6U5gm.js.map +1 -0
- package/dist/web/assets/table-BzjWcs87.js +2 -1
- package/dist/web/assets/table-BzjWcs87.js.map +1 -0
- package/dist/web/assets/terminal-tab-XKe1TZiV.js +2 -1
- package/dist/web/assets/terminal-tab-XKe1TZiV.js.map +1 -0
- package/dist/web/assets/text-wrap-DJz9Bgpa.js +2 -1
- package/dist/web/assets/text-wrap-DJz9Bgpa.js.map +1 -0
- package/dist/web/assets/use-blob-url-QX-XajU8.js +2 -1
- package/dist/web/assets/use-blob-url-QX-XajU8.js.map +1 -0
- package/dist/web/assets/use-monaco-theme-BePWbY58.js +2 -1
- package/dist/web/assets/use-monaco-theme-BePWbY58.js.map +1 -0
- package/dist/web/assets/utils-CQux7CsO.js +2 -1
- package/dist/web/assets/utils-CQux7CsO.js.map +1 -0
- package/dist/web/assets/vendor-markdown-0Mxgxy0L.js +2 -1
- package/dist/web/assets/vendor-markdown-0Mxgxy0L.js.map +1 -0
- package/dist/web/assets/vendor-mermaid-Cl50p6TB.js +2 -1
- package/dist/web/assets/vendor-mermaid-Cl50p6TB.js.map +1 -0
- package/dist/web/assets/vendor-ui-UXCWAcmi.js +2 -1
- package/dist/web/assets/vendor-ui-UXCWAcmi.js.map +1 -0
- package/dist/web/assets/vendor-xterm-K3_Xwigj.js +2 -1
- package/dist/web/assets/vendor-xterm-K3_Xwigj.js.map +1 -0
- package/dist/web/assets/video-preview-wHVbAYar.js +2 -1
- package/dist/web/assets/video-preview-wHVbAYar.js.map +1 -0
- package/dist/web/assets/x-BPReZWnP.js +2 -1
- package/dist/web/assets/x-BPReZWnP.js.map +1 -0
- package/dist/web/sw.js +2 -1
- package/dist/web/sw.js.map +1 -0
- package/package.json +1 -1
- package/vite.config.ts +1 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{b as t,x as n}from"./vendor-markdown-0Mxgxy0L.js";import{i as r,r as i}from"./glide-data-grid-CqT8WzTs.js";import{n as a,t as o}from"./use-monaco-theme-BePWbY58.js";var s=e(n(),1),c=t();function l(e,t){let n=e.split(`
|
|
2
2
|
`),r=0;for(let e=0;e<n.length;e++){let i=n[e].trim();e<t-1&&i.endsWith(`;`)&&(r=e+1)}let i=n.length-1;for(let e=t-1;e<n.length;e++)if(n[e].trim().endsWith(`;`)){i=e;break}for(;r<=i;){let e=n[r].trim();if(e&&!e.startsWith(`--`))break;r++}return n.slice(r,i+1).join(`
|
|
3
|
-
`).trim()}function u({onExecute:e,loading:t,defaultValue:n=`SELECT * FROM `,schemaInfo:u,cacheKey:d}){let f=d?`ppm:sql-query:${d}`:null,[p,m]=(0,s.useState)(()=>{if(f)try{return sessionStorage.getItem(f)??n}catch{}return n}),h=(0,s.useRef)(!1),g=(0,s.useRef)(null),_=(0,s.useRef)(null),v=(0,s.useRef)(null),y=(0,s.useRef)(e);y.current=e;let b=o();(0,s.useEffect)(()=>{if(!(!_.current||!u))return v.current?.dispose(),i(),v.current=_.current.languages.registerCompletionItemProvider(`sql`,r(_.current,u)),()=>{v.current?.dispose()}},[u]);let x=(0,s.useCallback)((e,t)=>{g.current=e,_.current=t,e.addAction({id:`run-query-at-cursor`,label:`Run Statement at Cursor`,keybindings:[t.KeyMod.CtrlCmd|t.KeyCode.Enter],run:e=>{let t=e.getPosition();if(!t)return;let n=l(e.getValue(),t.lineNumber);n&&y.current(n)}}),u&&(v.current?.dispose(),v.current=t.languages.registerCompletionItemProvider(`sql`,r(t,u)))},[u]);return(0,s.useEffect)(()=>{h.current||m(n)},[n]),(0,c.jsx)(`div`,{className:`h-full overflow-hidden`,children:(0,c.jsx)(a,{height:`100%`,language:`sql`,theme:b,value:p,onChange:e=>{let t=e??``;if(m(t),h.current=!0,f)try{sessionStorage.setItem(f,t)}catch{}},onMount:x,options:{minimap:{enabled:!1},lineNumbers:`off`,scrollBeyondLastLine:!1,wordWrap:`on`,fontSize:12,tabSize:2,renderLineHighlight:`none`,overviewRulerLanes:0,hideCursorInOverviewRuler:!0,scrollbar:{vertical:`auto`,horizontal:`auto`,verticalScrollbarSize:6,horizontalScrollbarSize:6},padding:{top:4,bottom:4},lineDecorationsWidth:4,lineNumbersMinChars:0,glyphMargin:!1,folding:!1,fixedOverflowWidgets:!0}})})}export{u as t};
|
|
3
|
+
`).trim()}function u({onExecute:e,loading:t,defaultValue:n=`SELECT * FROM `,schemaInfo:u,cacheKey:d}){let f=d?`ppm:sql-query:${d}`:null,[p,m]=(0,s.useState)(()=>{if(f)try{return sessionStorage.getItem(f)??n}catch{}return n}),h=(0,s.useRef)(!1),g=(0,s.useRef)(null),_=(0,s.useRef)(null),v=(0,s.useRef)(null),y=(0,s.useRef)(e);y.current=e;let b=o();(0,s.useEffect)(()=>{if(!(!_.current||!u))return v.current?.dispose(),i(),v.current=_.current.languages.registerCompletionItemProvider(`sql`,r(_.current,u)),()=>{v.current?.dispose()}},[u]);let x=(0,s.useCallback)((e,t)=>{g.current=e,_.current=t,e.addAction({id:`run-query-at-cursor`,label:`Run Statement at Cursor`,keybindings:[t.KeyMod.CtrlCmd|t.KeyCode.Enter],run:e=>{let t=e.getPosition();if(!t)return;let n=l(e.getValue(),t.lineNumber);n&&y.current(n)}}),u&&(v.current?.dispose(),v.current=t.languages.registerCompletionItemProvider(`sql`,r(t,u)))},[u]);return(0,s.useEffect)(()=>{h.current||m(n)},[n]),(0,c.jsx)(`div`,{className:`h-full overflow-hidden`,children:(0,c.jsx)(a,{height:`100%`,language:`sql`,theme:b,value:p,onChange:e=>{let t=e??``;if(m(t),h.current=!0,f)try{sessionStorage.setItem(f,t)}catch{}},onMount:x,options:{minimap:{enabled:!1},lineNumbers:`off`,scrollBeyondLastLine:!1,wordWrap:`on`,fontSize:12,tabSize:2,renderLineHighlight:`none`,overviewRulerLanes:0,hideCursorInOverviewRuler:!0,scrollbar:{vertical:`auto`,horizontal:`auto`,verticalScrollbarSize:6,horizontalScrollbarSize:6},padding:{top:4,bottom:4},lineDecorationsWidth:4,lineNumbersMinChars:0,glyphMargin:!1,folding:!1,fixedOverflowWidgets:!0}})})}export{u as t};
|
|
4
|
+
//# sourceMappingURL=sql-query-editor-lSlKMPlG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sql-query-editor-lSlKMPlG.js","names":[],"sources":["../../../src/web/components/database/sql-query-editor.tsx"],"sourcesContent":["import { useState, useCallback, useRef, useEffect } from \"react\";\nimport Editor, { type OnMount } from \"@monaco-editor/react\";\nimport type * as MonacoType from \"monaco-editor\";\nimport { useMonacoTheme } from \"@/lib/use-monaco-theme\";\nimport { createSqlCompletionProvider, clearCompletionCache, type SchemaInfo } from \"./sql-completion-provider\";\n\ninterface SqlQueryEditorProps {\n onExecute: (sql: string) => void;\n loading: boolean;\n defaultValue?: string;\n schemaInfo?: SchemaInfo;\n /** Unique key for caching query text in sessionStorage (e.g. connectionId) */\n cacheKey?: string;\n}\n\n/** Find the SQL statement surrounding the cursor line (split by ;) */\nexport function getStatementAtCursor(text: string, cursorLine: number): string {\n const lines = text.split(\"\\n\");\n // Find statement boundaries (lines where a statement ends with ;)\n let stmtStart = 0;\n for (let i = 0; i < lines.length; i++) {\n const trimmed = lines[i]!.trim();\n if (i < cursorLine - 1 && trimmed.endsWith(\";\")) {\n stmtStart = i + 1;\n }\n }\n // Find statement end\n let stmtEnd = lines.length - 1;\n for (let i = cursorLine - 1; i < lines.length; i++) {\n const trimmed = lines[i]!.trim();\n if (trimmed.endsWith(\";\")) {\n stmtEnd = i;\n break;\n }\n }\n // Skip leading empty/comment lines\n while (stmtStart <= stmtEnd) {\n const t = lines[stmtStart]!.trim();\n if (t && !t.startsWith(\"--\")) break;\n stmtStart++;\n }\n return lines.slice(stmtStart, stmtEnd + 1).join(\"\\n\").trim();\n}\n\n/** Shared Monaco-based SQL query editor (editor only, no results) */\nexport function SqlQueryEditor({ onExecute, loading, defaultValue = \"SELECT * FROM \", schemaInfo, cacheKey }: SqlQueryEditorProps) {\n const storageKey = cacheKey ? `ppm:sql-query:${cacheKey}` : null;\n const [query, setQuery] = useState(() => {\n if (storageKey) { try { return sessionStorage.getItem(storageKey) ?? defaultValue; } catch { /* */ } }\n return defaultValue;\n });\n const userEditedRef = useRef(false);\n const editorRef = useRef<MonacoType.editor.IStandaloneCodeEditor | null>(null);\n const monacoRef = useRef<typeof MonacoType | null>(null);\n const disposableRef = useRef<MonacoType.IDisposable | null>(null);\n const onExecuteRef = useRef(onExecute);\n onExecuteRef.current = onExecute;\n const monacoTheme = useMonacoTheme();\n\n useEffect(() => {\n if (!monacoRef.current || !schemaInfo) return;\n disposableRef.current?.dispose();\n clearCompletionCache();\n disposableRef.current = monacoRef.current.languages.registerCompletionItemProvider(\n \"sql\",\n createSqlCompletionProvider(monacoRef.current, schemaInfo),\n );\n return () => { disposableRef.current?.dispose(); };\n }, [schemaInfo]);\n\n const handleMount: OnMount = useCallback((editor, monaco) => {\n editorRef.current = editor;\n monacoRef.current = monaco;\n\n // Cmd/Ctrl+Enter: run statement at cursor\n editor.addAction({\n id: \"run-query-at-cursor\",\n label: \"Run Statement at Cursor\",\n keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter],\n run: (ed) => {\n const pos = ed.getPosition();\n if (!pos) return;\n const text = ed.getValue();\n const stmt = getStatementAtCursor(text, pos.lineNumber);\n if (stmt) onExecuteRef.current(stmt);\n },\n });\n\n if (schemaInfo) {\n disposableRef.current?.dispose();\n disposableRef.current = monaco.languages.registerCompletionItemProvider(\n \"sql\",\n createSqlCompletionProvider(monaco, schemaInfo),\n );\n }\n }, [schemaInfo]);\n\n // Sync from defaultValue only if user hasn't manually edited\n useEffect(() => {\n if (!userEditedRef.current) setQuery(defaultValue);\n }, [defaultValue]);\n\n return (\n <div className=\"h-full overflow-hidden\">\n <Editor\n height=\"100%\"\n language=\"sql\"\n theme={monacoTheme}\n value={query}\n onChange={(v) => { const val = v ?? \"\"; setQuery(val); userEditedRef.current = true; if (storageKey) try { sessionStorage.setItem(storageKey, val); } catch {} }}\n onMount={handleMount}\n options={{\n minimap: { enabled: false },\n lineNumbers: \"off\",\n scrollBeyondLastLine: false,\n wordWrap: \"on\",\n fontSize: 12,\n tabSize: 2,\n renderLineHighlight: \"none\",\n overviewRulerLanes: 0,\n hideCursorInOverviewRuler: true,\n scrollbar: { vertical: \"auto\", horizontal: \"auto\", verticalScrollbarSize: 6, horizontalScrollbarSize: 6 },\n padding: { top: 4, bottom: 4 },\n lineDecorationsWidth: 4,\n lineNumbersMinChars: 0,\n glyphMargin: false,\n folding: false,\n fixedOverflowWidgets: true,\n }}\n />\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{b as t,x as n}from"./vendor-markdown-0Mxgxy0L.js";import"./vendor-ui-UXCWAcmi.js";import{t as r}from"./database-DOWH9-Vv.js";import{t as i}from"./glide-data-grid-CqT8WzTs.js";import{t as a}from"./refresh-cw-BjrAbUJe.js";import{t as o}from"./table-BzjWcs87.js";import{i as s,t as c}from"./api-client-DIhJ5qVW.js";import"./settings-store-CVrIYYCB.js";import"./vendor-mermaid-Cl50p6TB.js";import"./tab-store-S9w6U5gm.js";import{G as l,rt as u}from"./index-DJtqbPFT.js";import"./data-grid-types-BISkUXAY.js";import"./use-monaco-theme-BePWbY58.js";import{t as d}from"./sql-query-editor-lSlKMPlG.js";var f=e(n(),1);function p(e,t,n){let[r,i]=(0,f.useState)([]),[a,o]=(0,f.useState)(null),[l,u]=(0,f.useState)(null),[d,p]=(0,f.useState)([]),[m,h]=(0,f.useState)(!1),[g,_]=(0,f.useState)(null),[v,y]=(0,f.useState)(1),[b,x]=(0,f.useState)(null),[S,C]=(0,f.useState)(null),[w,T]=(0,f.useState)(!1),E=n?`/api/db/connections/${n}`:null,D=E??`${s(e)}/sqlite`,O=E?``:`path=${encodeURIComponent(t)}`,k=(0,f.useCallback)(async()=>{h(!0),_(null);try{let e=E?`?cached=1`:O?`?${O}`:``,t=await c.get(`${D}/tables${e}`);i(t),!E&&t.length>0&&!a&&o(t[0].name)}catch(e){_(e.message)}finally{h(!1)}},[D,O,E]);(0,f.useEffect)(()=>{k()},[k]);let A=(0,f.useCallback)(async()=>{if(a){h(!0);try{let e=O?`${O}&`:``,[t,n]=await Promise.all([c.get(`${D}/data?${e}table=${encodeURIComponent(a)}&page=${v}&limit=100`),c.get(`${D}/schema?${e}table=${encodeURIComponent(a)}`)]);u(t),p(n)}catch(e){_(e.message)}finally{h(!1)}}},[D,O,a,v]);return(0,f.useEffect)(()=>{A()},[A]),{tables:r,selectedTable:a,selectTable:(0,f.useCallback)(e=>{o(e),y(1),x(null)},[]),tableData:l,schema:d,loading:m,error:g,page:v,setPage:y,queryResult:b,queryError:S,queryLoading:w,executeQuery:(0,f.useCallback)(async e=>{T(!0),C(null);try{let n=E?{sql:e}:{path:t,sql:e},r=await c.post(`${D}/query`,n);x(r),r.changeType===`modify`&&A()}catch(e){C(e.message)}finally{T(!1)}},[D,E,t,A]),updateCell:(0,f.useCallback)(async(e,n,r)=>{if(a)try{E?await c.put(`${D}/cell`,{table:a,pkColumn:`rowid`,pkValue:e,column:n,value:r}):await c.put(`${D}/cell`,{path:t,table:a,rowid:e,column:n,value:r}),A()}catch(e){_(e.message)}},[D,E,t,a,A]),deleteRow:(0,f.useCallback)(async e=>{if(a)try{E?await c.del(`${D}/row`,{table:a,pkColumn:`rowid`,pkValue:e}):await c.del(`${D}/row`,{path:t,table:a,rowid:e}),A(),k()}catch(e){_(e.message)}},[D,E,t,a,A,k]),refreshTables:k,refreshData:A}}var m=t();function h({tables:e,selectedTable:t,onSelect:n,onRefresh:r}){return(0,m.jsxs)(`div`,{className:`w-48 shrink-0 flex flex-col bg-background overflow-hidden`,children:[(0,m.jsxs)(`div`,{className:`flex items-center justify-between px-3 py-2 border-b border-border`,children:[(0,m.jsx)(`span`,{className:`text-xs font-medium text-muted-foreground uppercase tracking-wider`,children:`Tables`}),(0,m.jsx)(`button`,{type:`button`,onClick:r,className:`text-muted-foreground hover:text-foreground transition-colors`,title:`Refresh tables`,children:(0,m.jsx)(a,{className:`size-3`})})]}),(0,m.jsxs)(`div`,{className:`flex-1 overflow-y-auto`,children:[e.map(e=>(0,m.jsxs)(`button`,{type:`button`,onClick:()=>n(e.name),className:`w-full flex items-center gap-2 px-3 py-1.5 text-left text-xs transition-colors ${t===e.name?`bg-muted text-foreground`:`text-muted-foreground hover:bg-muted/50 hover:text-foreground`}`,children:[(0,m.jsx)(o,{className:`size-3 shrink-0`}),(0,m.jsx)(`span`,{className:`truncate flex-1`,children:e.name}),(0,m.jsx)(`span`,{className:`text-[10px] opacity-60`,children:e.rowCount})]},e.name)),e.length===0&&(0,m.jsx)(`p`,{className:`px-3 py-4 text-xs text-muted-foreground text-center`,children:`No tables found`})]})]})}function g({onExecute:e,loading:t}){return(0,m.jsx)(d,{onExecute:e,loading:t})}function _({metadata:e}){let t=e?.filePath,n=e?.projectName,i=e?.connectionId,a=e?.tableName,[o,s]=(0,f.useState)(!1);return i?(0,m.jsx)(v,{projectName:``,dbPath:``,connectionId:i,connectionName:e?.connectionName,initialTable:a,queryPanelOpen:o,onToggleQueryPanel:()=>s(e=>!e),hideTableList:!0}):!t||!n?(0,m.jsxs)(`div`,{className:`flex items-center justify-center h-full text-text-secondary text-sm`,children:[(0,m.jsx)(r,{className:`size-5 mr-2`}),` No database file selected.`]}):(0,m.jsx)(v,{projectName:n,dbPath:t,queryPanelOpen:o,onToggleQueryPanel:()=>s(e=>!e)})}function v({projectName:e,dbPath:t,connectionId:n,connectionName:a,initialTable:o,queryPanelOpen:s,onToggleQueryPanel:c,hideTableList:d}){let _=p(e,t,n),v=(0,f.useRef)(!1);return(0,f.useEffect)(()=>{o&&!v.current&&_.tables.length>0&&(v.current=!0,_.selectTable(o))},[o,_.tables]),_.error&&_.tables.length===0?(0,m.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-full gap-3 text-text-secondary`,children:[(0,m.jsx)(u,{className:`size-10 text-destructive`}),(0,m.jsx)(`p`,{className:`text-sm`,children:_.error})]}):_.loading&&_.tables.length===0?(0,m.jsxs)(`div`,{className:`flex items-center justify-center h-full gap-2 text-text-secondary`,children:[(0,m.jsx)(l,{className:`size-5 animate-spin`}),(0,m.jsx)(`span`,{className:`text-sm`,children:`Loading database...`})]}):(0,m.jsxs)(`div`,{className:`flex h-full w-full overflow-hidden`,children:[!d&&(0,m.jsx)(h,{tables:_.tables,selectedTable:_.selectedTable,onSelect:_.selectTable,onRefresh:_.refreshTables}),(0,m.jsxs)(`div`,{className:`flex-1 flex flex-col overflow-hidden ${d?``:`border-l border-border`}`,children:[(0,m.jsxs)(`div`,{className:`flex items-center gap-2 px-3 py-1.5 border-b border-border bg-background shrink-0`,children:[(0,m.jsx)(r,{className:`size-3.5 text-muted-foreground`}),(0,m.jsx)(`span`,{className:`text-xs text-muted-foreground truncate`,children:a??t}),(0,m.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:_.selectedTable&&`/ ${_.selectedTable}`}),(0,m.jsx)(`div`,{className:`ml-auto`,children:(0,m.jsx)(`button`,{type:`button`,onClick:c,className:`px-2 py-1 rounded text-xs transition-colors ${s?`bg-muted text-foreground`:`text-muted-foreground hover:text-foreground`}`,children:`SQL`})})]}),(0,m.jsx)(`div`,{className:`flex-1 overflow-hidden ${s?`max-h-[60%]`:``}`,children:_.tableData?(0,m.jsx)(i,{columns:_.tableData.columns,rows:_.tableData.rows,total:_.tableData.total,limit:_.tableData.limit,schema:_.schema.map(e=>({name:e.name,type:e.type,nullable:!e.notnull,pk:!!e.pk,defaultValue:e.dflt_value,fk:e.fk??null})),loading:_.loading,page:_.page,onPageChange:_.setPage,onCellUpdate:(e,t,n,r)=>_.updateCell(t,n,r),onRowDelete:(e,t)=>_.deleteRow(t)}):(0,m.jsx)(`div`,{className:`flex items-center justify-center h-full text-xs text-muted-foreground`,children:_.loading?(0,m.jsx)(l,{className:`size-4 animate-spin`}):`Select a table`})}),s&&(0,m.jsx)(`div`,{className:`border-t border-border h-[40%] shrink-0`,children:(0,m.jsx)(g,{onExecute:_.executeQuery,loading:_.queryLoading})})]})]})}export{_ as SqliteViewer};
|
|
1
|
+
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{b as t,x as n}from"./vendor-markdown-0Mxgxy0L.js";import"./vendor-ui-UXCWAcmi.js";import{t as r}from"./database-DOWH9-Vv.js";import{t as i}from"./glide-data-grid-CqT8WzTs.js";import{t as a}from"./refresh-cw-BjrAbUJe.js";import{t as o}from"./table-BzjWcs87.js";import{i as s,t as c}from"./api-client-DIhJ5qVW.js";import"./settings-store-CVrIYYCB.js";import"./vendor-mermaid-Cl50p6TB.js";import"./tab-store-S9w6U5gm.js";import{G as l,rt as u}from"./index-DJtqbPFT.js";import"./data-grid-types-BISkUXAY.js";import"./use-monaco-theme-BePWbY58.js";import{t as d}from"./sql-query-editor-lSlKMPlG.js";var f=e(n(),1);function p(e,t,n){let[r,i]=(0,f.useState)([]),[a,o]=(0,f.useState)(null),[l,u]=(0,f.useState)(null),[d,p]=(0,f.useState)([]),[m,h]=(0,f.useState)(!1),[g,_]=(0,f.useState)(null),[v,y]=(0,f.useState)(1),[b,x]=(0,f.useState)(null),[S,C]=(0,f.useState)(null),[w,T]=(0,f.useState)(!1),E=n?`/api/db/connections/${n}`:null,D=E??`${s(e)}/sqlite`,O=E?``:`path=${encodeURIComponent(t)}`,k=(0,f.useCallback)(async()=>{h(!0),_(null);try{let e=E?`?cached=1`:O?`?${O}`:``,t=await c.get(`${D}/tables${e}`);i(t),!E&&t.length>0&&!a&&o(t[0].name)}catch(e){_(e.message)}finally{h(!1)}},[D,O,E]);(0,f.useEffect)(()=>{k()},[k]);let A=(0,f.useCallback)(async()=>{if(a){h(!0);try{let e=O?`${O}&`:``,[t,n]=await Promise.all([c.get(`${D}/data?${e}table=${encodeURIComponent(a)}&page=${v}&limit=100`),c.get(`${D}/schema?${e}table=${encodeURIComponent(a)}`)]);u(t),p(n)}catch(e){_(e.message)}finally{h(!1)}}},[D,O,a,v]);return(0,f.useEffect)(()=>{A()},[A]),{tables:r,selectedTable:a,selectTable:(0,f.useCallback)(e=>{o(e),y(1),x(null)},[]),tableData:l,schema:d,loading:m,error:g,page:v,setPage:y,queryResult:b,queryError:S,queryLoading:w,executeQuery:(0,f.useCallback)(async e=>{T(!0),C(null);try{let n=E?{sql:e}:{path:t,sql:e},r=await c.post(`${D}/query`,n);x(r),r.changeType===`modify`&&A()}catch(e){C(e.message)}finally{T(!1)}},[D,E,t,A]),updateCell:(0,f.useCallback)(async(e,n,r)=>{if(a)try{E?await c.put(`${D}/cell`,{table:a,pkColumn:`rowid`,pkValue:e,column:n,value:r}):await c.put(`${D}/cell`,{path:t,table:a,rowid:e,column:n,value:r}),A()}catch(e){_(e.message)}},[D,E,t,a,A]),deleteRow:(0,f.useCallback)(async e=>{if(a)try{E?await c.del(`${D}/row`,{table:a,pkColumn:`rowid`,pkValue:e}):await c.del(`${D}/row`,{path:t,table:a,rowid:e}),A(),k()}catch(e){_(e.message)}},[D,E,t,a,A,k]),refreshTables:k,refreshData:A}}var m=t();function h({tables:e,selectedTable:t,onSelect:n,onRefresh:r}){return(0,m.jsxs)(`div`,{className:`w-48 shrink-0 flex flex-col bg-background overflow-hidden`,children:[(0,m.jsxs)(`div`,{className:`flex items-center justify-between px-3 py-2 border-b border-border`,children:[(0,m.jsx)(`span`,{className:`text-xs font-medium text-muted-foreground uppercase tracking-wider`,children:`Tables`}),(0,m.jsx)(`button`,{type:`button`,onClick:r,className:`text-muted-foreground hover:text-foreground transition-colors`,title:`Refresh tables`,children:(0,m.jsx)(a,{className:`size-3`})})]}),(0,m.jsxs)(`div`,{className:`flex-1 overflow-y-auto`,children:[e.map(e=>(0,m.jsxs)(`button`,{type:`button`,onClick:()=>n(e.name),className:`w-full flex items-center gap-2 px-3 py-1.5 text-left text-xs transition-colors ${t===e.name?`bg-muted text-foreground`:`text-muted-foreground hover:bg-muted/50 hover:text-foreground`}`,children:[(0,m.jsx)(o,{className:`size-3 shrink-0`}),(0,m.jsx)(`span`,{className:`truncate flex-1`,children:e.name}),(0,m.jsx)(`span`,{className:`text-[10px] opacity-60`,children:e.rowCount})]},e.name)),e.length===0&&(0,m.jsx)(`p`,{className:`px-3 py-4 text-xs text-muted-foreground text-center`,children:`No tables found`})]})]})}function g({onExecute:e,loading:t}){return(0,m.jsx)(d,{onExecute:e,loading:t})}function _({metadata:e}){let t=e?.filePath,n=e?.projectName,i=e?.connectionId,a=e?.tableName,[o,s]=(0,f.useState)(!1);return i?(0,m.jsx)(v,{projectName:``,dbPath:``,connectionId:i,connectionName:e?.connectionName,initialTable:a,queryPanelOpen:o,onToggleQueryPanel:()=>s(e=>!e),hideTableList:!0}):!t||!n?(0,m.jsxs)(`div`,{className:`flex items-center justify-center h-full text-text-secondary text-sm`,children:[(0,m.jsx)(r,{className:`size-5 mr-2`}),` No database file selected.`]}):(0,m.jsx)(v,{projectName:n,dbPath:t,queryPanelOpen:o,onToggleQueryPanel:()=>s(e=>!e)})}function v({projectName:e,dbPath:t,connectionId:n,connectionName:a,initialTable:o,queryPanelOpen:s,onToggleQueryPanel:c,hideTableList:d}){let _=p(e,t,n),v=(0,f.useRef)(!1);return(0,f.useEffect)(()=>{o&&!v.current&&_.tables.length>0&&(v.current=!0,_.selectTable(o))},[o,_.tables]),_.error&&_.tables.length===0?(0,m.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-full gap-3 text-text-secondary`,children:[(0,m.jsx)(u,{className:`size-10 text-destructive`}),(0,m.jsx)(`p`,{className:`text-sm`,children:_.error})]}):_.loading&&_.tables.length===0?(0,m.jsxs)(`div`,{className:`flex items-center justify-center h-full gap-2 text-text-secondary`,children:[(0,m.jsx)(l,{className:`size-5 animate-spin`}),(0,m.jsx)(`span`,{className:`text-sm`,children:`Loading database...`})]}):(0,m.jsxs)(`div`,{className:`flex h-full w-full overflow-hidden`,children:[!d&&(0,m.jsx)(h,{tables:_.tables,selectedTable:_.selectedTable,onSelect:_.selectTable,onRefresh:_.refreshTables}),(0,m.jsxs)(`div`,{className:`flex-1 flex flex-col overflow-hidden ${d?``:`border-l border-border`}`,children:[(0,m.jsxs)(`div`,{className:`flex items-center gap-2 px-3 py-1.5 border-b border-border bg-background shrink-0`,children:[(0,m.jsx)(r,{className:`size-3.5 text-muted-foreground`}),(0,m.jsx)(`span`,{className:`text-xs text-muted-foreground truncate`,children:a??t}),(0,m.jsx)(`span`,{className:`text-xs text-muted-foreground`,children:_.selectedTable&&`/ ${_.selectedTable}`}),(0,m.jsx)(`div`,{className:`ml-auto`,children:(0,m.jsx)(`button`,{type:`button`,onClick:c,className:`px-2 py-1 rounded text-xs transition-colors ${s?`bg-muted text-foreground`:`text-muted-foreground hover:text-foreground`}`,children:`SQL`})})]}),(0,m.jsx)(`div`,{className:`flex-1 overflow-hidden ${s?`max-h-[60%]`:``}`,children:_.tableData?(0,m.jsx)(i,{columns:_.tableData.columns,rows:_.tableData.rows,total:_.tableData.total,limit:_.tableData.limit,schema:_.schema.map(e=>({name:e.name,type:e.type,nullable:!e.notnull,pk:!!e.pk,defaultValue:e.dflt_value,fk:e.fk??null})),loading:_.loading,page:_.page,onPageChange:_.setPage,onCellUpdate:(e,t,n,r)=>_.updateCell(t,n,r),onRowDelete:(e,t)=>_.deleteRow(t)}):(0,m.jsx)(`div`,{className:`flex items-center justify-center h-full text-xs text-muted-foreground`,children:_.loading?(0,m.jsx)(l,{className:`size-4 animate-spin`}):`Select a table`})}),s&&(0,m.jsx)(`div`,{className:`border-t border-border h-[40%] shrink-0`,children:(0,m.jsx)(g,{onExecute:_.executeQuery,loading:_.queryLoading})})]})]})}export{_ as SqliteViewer};
|
|
2
|
+
//# sourceMappingURL=sqlite-viewer-DwTatNwI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-viewer-DwTatNwI.js","names":[],"sources":["../../../src/web/components/sqlite/use-sqlite.ts","../../../src/web/components/sqlite/sqlite-table-list.tsx","../../../src/web/components/sqlite/sqlite-query-editor.tsx","../../../src/web/components/sqlite/sqlite-viewer.tsx"],"sourcesContent":["import { useState, useEffect, useCallback } from \"react\";\nimport { api, projectUrl } from \"@/lib/api-client\";\n\nexport interface TableInfo { name: string; rowCount: number }\nexport interface ColumnInfo { cid: number; name: string; type: string; notnull: boolean; pk: boolean; dflt_value: string | null; fk?: { table: string; column: string } | null }\nexport interface QueryResult { columns: string[]; rows: Record<string, unknown>[]; rowsAffected: number; changeType: \"select\" | \"modify\"; executionTimeMs?: number }\ninterface TableData { columns: string[]; rows: Record<string, unknown>[]; total: number; page: number; limit: number }\n\nexport function useSqlite(projectName: string, dbPath: string, connectionId?: number) {\n const [tables, setTables] = useState<TableInfo[]>([]);\n const [selectedTable, setSelectedTable] = useState<string | null>(null);\n const [tableData, setTableData] = useState<TableData | null>(null);\n const [schema, setSchema] = useState<ColumnInfo[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [page, setPage] = useState(1);\n const [queryResult, setQueryResult] = useState<QueryResult | null>(null);\n const [queryError, setQueryError] = useState<string | null>(null);\n const [queryLoading, setQueryLoading] = useState(false);\n\n // When connectionId present, use unified API; otherwise use project-scoped API\n const unifiedBase = connectionId ? `/api/db/connections/${connectionId}` : null;\n const base = unifiedBase ?? `${projectUrl(projectName)}/sqlite`;\n const qs = unifiedBase ? \"\" : `path=${encodeURIComponent(dbPath)}`;\n\n // Fetch tables on mount — use cache when connectionId (sidebar handles live sync)\n const fetchTables = useCallback(async () => {\n setLoading(true);\n setError(null);\n try {\n const qsPart = unifiedBase ? \"?cached=1\" : qs ? `?${qs}` : \"\";\n const data = await api.get<TableInfo[]>(`${base}/tables${qsPart}`);\n setTables(data);\n if (!unifiedBase && data.length > 0 && !selectedTable) setSelectedTable(data[0]!.name);\n } catch (e) {\n setError((e as Error).message);\n } finally {\n setLoading(false);\n }\n }, [base, qs, unifiedBase]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => { fetchTables(); }, [fetchTables]);\n\n // Fetch table data when selection or page changes\n const fetchTableData = useCallback(async () => {\n if (!selectedTable) return;\n setLoading(true);\n try {\n const qsPrefix = qs ? `${qs}&` : \"\";\n const [data, cols] = await Promise.all([\n api.get<TableData>(`${base}/data?${qsPrefix}table=${encodeURIComponent(selectedTable)}&page=${page}&limit=100`),\n api.get<ColumnInfo[]>(`${base}/schema?${qsPrefix}table=${encodeURIComponent(selectedTable)}`),\n ]);\n setTableData(data);\n setSchema(cols);\n } catch (e) {\n setError((e as Error).message);\n } finally {\n setLoading(false);\n }\n }, [base, qs, selectedTable, page]); // eslint-disable-line react-hooks/exhaustive-deps\n\n useEffect(() => { fetchTableData(); }, [fetchTableData]);\n\n const selectTable = useCallback((name: string) => {\n setSelectedTable(name);\n setPage(1);\n setQueryResult(null);\n }, []);\n\n const executeQuery = useCallback(async (sql: string) => {\n setQueryLoading(true);\n setQueryError(null);\n try {\n const body = unifiedBase ? { sql } : { path: dbPath, sql };\n const result = await api.post<QueryResult>(`${base}/query`, body);\n setQueryResult(result);\n if (result.changeType === \"modify\") fetchTableData();\n } catch (e) {\n setQueryError((e as Error).message);\n } finally {\n setQueryLoading(false);\n }\n }, [base, unifiedBase, dbPath, fetchTableData]);\n\n const updateCell = useCallback(async (rowid: number, column: string, value: unknown) => {\n if (!selectedTable) return;\n try {\n if (unifiedBase) {\n await api.put(`${base}/cell`, { table: selectedTable, pkColumn: \"rowid\", pkValue: rowid, column, value });\n } else {\n await api.put(`${base}/cell`, { path: dbPath, table: selectedTable, rowid, column, value });\n }\n fetchTableData();\n } catch (e) {\n setError((e as Error).message);\n }\n }, [base, unifiedBase, dbPath, selectedTable, fetchTableData]);\n\n const deleteRow = useCallback(async (rowid: number) => {\n if (!selectedTable) return;\n try {\n if (unifiedBase) {\n await api.del(`${base}/row`, { table: selectedTable, pkColumn: \"rowid\", pkValue: rowid });\n } else {\n await api.del(`${base}/row`, { path: dbPath, table: selectedTable, rowid });\n }\n fetchTableData();\n fetchTables(); // refresh row counts\n } catch (e) {\n setError((e as Error).message);\n }\n }, [base, unifiedBase, dbPath, selectedTable, fetchTableData, fetchTables]);\n\n return {\n tables, selectedTable, selectTable, tableData, schema,\n loading, error, page, setPage,\n queryResult, queryError, queryLoading, executeQuery,\n updateCell, deleteRow, refreshTables: fetchTables, refreshData: fetchTableData,\n };\n}\n","import { Table, RefreshCw } from \"lucide-react\";\nimport type { TableInfo } from \"./use-sqlite\";\n\ninterface Props {\n tables: TableInfo[];\n selectedTable: string | null;\n onSelect: (name: string) => void;\n onRefresh: () => void;\n}\n\nexport function SqliteTableList({ tables, selectedTable, onSelect, onRefresh }: Props) {\n return (\n <div className=\"w-48 shrink-0 flex flex-col bg-background overflow-hidden\">\n <div className=\"flex items-center justify-between px-3 py-2 border-b border-border\">\n <span className=\"text-xs font-medium text-muted-foreground uppercase tracking-wider\">Tables</span>\n <button\n type=\"button\"\n onClick={onRefresh}\n className=\"text-muted-foreground hover:text-foreground transition-colors\"\n title=\"Refresh tables\"\n >\n <RefreshCw className=\"size-3\" />\n </button>\n </div>\n <div className=\"flex-1 overflow-y-auto\">\n {tables.map((t) => (\n <button\n key={t.name}\n type=\"button\"\n onClick={() => onSelect(t.name)}\n className={`w-full flex items-center gap-2 px-3 py-1.5 text-left text-xs transition-colors ${\n selectedTable === t.name\n ? \"bg-muted text-foreground\"\n : \"text-muted-foreground hover:bg-muted/50 hover:text-foreground\"\n }`}\n >\n <Table className=\"size-3 shrink-0\" />\n <span className=\"truncate flex-1\">{t.name}</span>\n <span className=\"text-[10px] opacity-60\">{t.rowCount}</span>\n </button>\n ))}\n {tables.length === 0 && (\n <p className=\"px-3 py-4 text-xs text-muted-foreground text-center\">No tables found</p>\n )}\n </div>\n </div>\n );\n}\n","import { SqlQueryEditor } from \"../database/sql-query-editor\";\n\ninterface Props {\n onExecute: (sql: string) => void;\n loading: boolean;\n}\n\nexport function SqliteQueryEditor({ onExecute, loading }: Props) {\n return <SqlQueryEditor onExecute={onExecute} loading={loading} />;\n}\n","import { useState, useEffect, useRef, useCallback } from \"react\";\nimport { Database, Loader2, AlertCircle } from \"lucide-react\";\nimport { useSqlite } from \"./use-sqlite\";\nimport { SqliteTableList } from \"./sqlite-table-list\";\nimport { GlideDataGrid } from \"../database/glide-data-grid\";\nimport { SqliteQueryEditor } from \"./sqlite-query-editor\";\n\ninterface SqliteViewerProps {\n metadata?: Record<string, unknown>;\n tabId?: string;\n}\n\nexport function SqliteViewer({ metadata }: SqliteViewerProps) {\n const filePath = metadata?.filePath as string | undefined;\n const projectName = metadata?.projectName as string | undefined;\n const connectionId = metadata?.connectionId as number | undefined;\n const initialTable = metadata?.tableName as string | undefined;\n const [queryPanelOpen, setQueryPanelOpen] = useState(false);\n\n // Connection-based mode: skip file selection requirement\n if (connectionId) {\n return (\n <SqliteViewerInner\n projectName=\"\"\n dbPath=\"\"\n connectionId={connectionId}\n connectionName={metadata?.connectionName as string | undefined}\n initialTable={initialTable}\n queryPanelOpen={queryPanelOpen}\n onToggleQueryPanel={() => setQueryPanelOpen((v) => !v)}\n hideTableList\n />\n );\n }\n\n if (!filePath || !projectName) {\n return (\n <div className=\"flex items-center justify-center h-full text-text-secondary text-sm\">\n <Database className=\"size-5 mr-2\" /> No database file selected.\n </div>\n );\n }\n\n return (\n <SqliteViewerInner\n projectName={projectName}\n dbPath={filePath}\n queryPanelOpen={queryPanelOpen}\n onToggleQueryPanel={() => setQueryPanelOpen((v) => !v)}\n />\n );\n}\n\nfunction SqliteViewerInner({\n projectName, dbPath, connectionId, connectionName, initialTable, queryPanelOpen, onToggleQueryPanel, hideTableList,\n}: {\n projectName: string; dbPath: string; connectionId?: number; connectionName?: string; initialTable?: string;\n queryPanelOpen: boolean; onToggleQueryPanel: () => void; hideTableList?: boolean;\n}) {\n const sqlite = useSqlite(projectName, dbPath, connectionId);\n\n // Jump to initial table from sidebar click\n const didInit = useRef(false);\n useEffect(() => {\n if (initialTable && !didInit.current && sqlite.tables.length > 0) {\n didInit.current = true;\n sqlite.selectTable(initialTable);\n }\n }, [initialTable, sqlite.tables]); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (sqlite.error && sqlite.tables.length === 0) {\n return (\n <div className=\"flex flex-col items-center justify-center h-full gap-3 text-text-secondary\">\n <AlertCircle className=\"size-10 text-destructive\" />\n <p className=\"text-sm\">{sqlite.error}</p>\n </div>\n );\n }\n\n if (sqlite.loading && sqlite.tables.length === 0) {\n return (\n <div className=\"flex items-center justify-center h-full gap-2 text-text-secondary\">\n <Loader2 className=\"size-5 animate-spin\" />\n <span className=\"text-sm\">Loading database...</span>\n </div>\n );\n }\n\n return (\n <div className=\"flex h-full w-full overflow-hidden\">\n {/* Left sidebar — table list (hidden when opened from database sidebar) */}\n {!hideTableList && (\n <SqliteTableList\n tables={sqlite.tables}\n selectedTable={sqlite.selectedTable}\n onSelect={sqlite.selectTable}\n onRefresh={sqlite.refreshTables}\n />\n )}\n\n {/* Main content area */}\n <div className={`flex-1 flex flex-col overflow-hidden ${!hideTableList ? \"border-l border-border\" : \"\"}`}>\n {/* Toolbar */}\n <div className=\"flex items-center gap-2 px-3 py-1.5 border-b border-border bg-background shrink-0\">\n <Database className=\"size-3.5 text-muted-foreground\" />\n <span className=\"text-xs text-muted-foreground truncate\">{connectionName ?? dbPath}</span>\n <span className=\"text-xs text-muted-foreground\">\n {sqlite.selectedTable && `/ ${sqlite.selectedTable}`}\n </span>\n <div className=\"ml-auto\">\n <button\n type=\"button\"\n onClick={onToggleQueryPanel}\n className={`px-2 py-1 rounded text-xs transition-colors ${queryPanelOpen ? \"bg-muted text-foreground\" : \"text-muted-foreground hover:text-foreground\"}`}\n >\n SQL\n </button>\n </div>\n </div>\n\n {/* Data grid — adapter from sqlite rowid-based API to GlideDataGrid's pk-based API */}\n <div className={`flex-1 overflow-hidden ${queryPanelOpen ? \"max-h-[60%]\" : \"\"}`}>\n {sqlite.tableData ? (\n <GlideDataGrid\n columns={sqlite.tableData.columns}\n rows={sqlite.tableData.rows}\n total={sqlite.tableData.total}\n limit={sqlite.tableData.limit}\n schema={sqlite.schema.map((c) => ({ name: c.name, type: c.type, nullable: !c.notnull, pk: !!c.pk, defaultValue: c.dflt_value, fk: c.fk ?? null }))}\n loading={sqlite.loading}\n page={sqlite.page}\n onPageChange={sqlite.setPage}\n onCellUpdate={(_pkCol, pkVal, col, val) => sqlite.updateCell(pkVal as number, col, val)}\n onRowDelete={(_pkCol, pkVal) => sqlite.deleteRow(pkVal as number)}\n />\n ) : (\n <div className=\"flex items-center justify-center h-full text-xs text-muted-foreground\">\n {sqlite.loading ? <Loader2 className=\"size-4 animate-spin\" /> : \"Select a table\"}\n </div>\n )}\n </div>\n\n {/* Query editor (collapsible) */}\n {queryPanelOpen && (\n <div className=\"border-t border-border h-[40%] shrink-0\">\n <SqliteQueryEditor\n onExecute={sqlite.executeQuery}\n loading={sqlite.queryLoading}\n />\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./react-DMIOAtcX.js";import{r as t}from"./utils-CQux7CsO.js";function n(){return`panel-${t()}`}function r(e=[],t=null){return{id:n(),tabs:e,activeTabId:t,tabHistory:t?[t]:[]}}function i(e){return e?1:3}function a(e,t){return e.map(e=>e.filter(e=>e!==t)).filter(e=>e.length>0)}function o(e,t){for(let n=0;n<e.length;n++){let r=e[n].indexOf(t);if(r!==-1)return{row:n,col:r}}return null}function s(e){let t=0;for(let n of Object.values(e))for(let e of n.tabs){let n=e.id.match(/^editor:untitled-(\d+)$/);n&&(t=Math.max(t,Number(n[1])))}return t+1}function c(e,n){switch(e){case`editor`:return n?.viewerKey?`editor:viewer:${n.viewerKey}`:n?.isUntitled?`editor:untitled-${n.untitledNumber??1}`:`editor:${n?.filePath??`untitled`}`;case`chat`:return`chat:${n?.providerId??`default`}/${n?.sessionId??t()}`;case`terminal`:return`terminal:${n?.terminalIndex??1}`;case`database`:return`database:${n?.connectionId??`default`}:${n?.tableName??``}`;case`sqlite`:return`sqlite:${n?.filePath??`default`}`;case`postgres`:return`postgres:${n?.connectionId??`default`}:${n?.tableName??``}`;case`extension`:return`extension:${String(n?.viewType??`unknown`).replace(/\.view$/,``)}`;case`git-diff`:return`git-diff:${n?.filePath??`unknown`}`;case`conflict-editor`:return`conflict-editor:${n?.filePath??`unknown`}`;case`settings`:return`settings`;case`ports`:return`ports`;default:return`${e}:${t()}`}}function l(e){let t={...e,panels:{...e.panels}};for(let[e,n]of Object.entries(t.panels)){let r=n.tabs.map(e=>{if(e.id.startsWith(`tab-`)){let t=c(e.type,e.metadata);return{...e,id:t}}return e}),i=new Map;n.tabs.forEach((e,t)=>{e.id!==r[t].id&&i.set(e.id,r[t].id)});let a=i.get(n.activeTabId??``)??n.activeTabId,o=n.tabHistory.map(e=>i.get(e)??e);t.panels[e]={...n,tabs:r,activeTabId:a,tabHistory:o}}return t}var u=`ppm-panels-`,d=`ppm-tabs-`;function f(e){return`${u}${e}`}function p(e,t){try{let n={...t,updatedAt:new Date().toISOString()};localStorage.setItem(f(e),JSON.stringify(n)),e!==`__global__`&&_(e,t)}catch{}}function m(e){try{let t=localStorage.getItem(f(e));if(t)return l(JSON.parse(t))}catch{}return y(e)}async function h(e){if(e===`__global__`)return null;try{let t={},n=localStorage.getItem(`ppm-auth-token`);n&&(t.Authorization=`Bearer ${n}`);let r=await fetch(`/api/project/${encodeURIComponent(e)}/workspace`,{headers:t});if(!r.ok)return null;let i=await r.json();return!i.ok||!i.data?null:{...i.data.layout,updatedAt:i.data.updatedAt}}catch{return null}}var g=new Map;function _(e,t){let n=g.get(e);n&&clearTimeout(n),g.set(e,setTimeout(async()=>{g.delete(e);try{let n={"Content-Type":`application/json`},r=localStorage.getItem(`ppm-auth-token`);r&&(n.Authorization=`Bearer ${r}`);let i=await fetch(`/api/project/${encodeURIComponent(e)}/workspace`,{method:`PUT`,headers:n,body:JSON.stringify({layout:t})});if(i.ok){let t=await i.json();if(t.data?.updatedAt){let n=`${u}${e}`,r=localStorage.getItem(n);if(r){let e=JSON.parse(r);e.updatedAt=t.data.updatedAt,localStorage.setItem(n,JSON.stringify(e))}}}}catch{}},1500))}function v(e,t){if(!e&&!t)return null;if(!e)return t;if(!t)return e;let n=new Date(e.updatedAt).getTime();return new Date(t.updatedAt).getTime()>=n?t:e}function y(e){try{let t=localStorage.getItem(`${d}${e}`);if(!t)return null;let n=JSON.parse(t);if(!n.tabs?.length)return null;let i=r(n.tabs,n.activeTabId),a={panels:{[i.id]:i},grid:[[i.id]],focusedPanelId:i.id};return p(e,a),localStorage.removeItem(`${d}${e}`),a}catch{return null}}var b=new Set([`settings`]),x=new Set([`projects`,`git-status`,`git-graph`]);function S(e,t){let n=e.filter(e=>e!==t);return n.push(t),n.length>50&&n.shift(),n}function C(){let e=r();return{panels:{[e.id]:e},grid:[[e.id]],focusedPanelId:e.id}}var w=e()((e,t)=>{function n(){let{currentProject:e,panels:n,grid:r,focusedPanelId:i}=t();if(!e)return;let a=new Set(r.flat()),o={};for(let[e,t]of Object.entries(n))a.has(e)&&(o[e]=t);p(e,{panels:o,grid:r,focusedPanelId:i})}function s(e){return Object.values(t().panels).find(t=>t.tabs.some(t=>t.id===e))}function l(e){return e??t().focusedPanelId}return{...C(),currentProject:null,projectGrids:{},projectFocused:{},switchProject:n=>{let{currentProject:i,panels:a,grid:o,focusedPanelId:s,projectGrids:c,projectFocused:l}=t();if(i===n)return;let u={...c},d={...l};if(i){u[i]=o,d[i]=s;let e=new Set(o.flat()),t={};for(let[n,r]of Object.entries(a))e.has(n)&&(t[n]=r);p(i,{panels:t,grid:o,focusedPanelId:s})}if(u[n]){let t=u[n];e({currentProject:n,grid:t,focusedPanelId:d[n]??t[0]?.[0]??``,projectGrids:u,projectFocused:d});return}let f=m(n);if(f&&Object.keys(f.panels).length>0){let t={};for(let[e,n]of Object.entries(f.panels)){let r=n.tabs.filter(e=>!x.has(e.type)),i=n.tabHistory.filter(e=>r.some(t=>t.id===e)),a=n.activeTabId&&r.some(e=>e.id===n.activeTabId)?n.activeTabId:i[i.length-1]??r[0]?.id??null;t[e]={...n,tabs:r,tabHistory:i,activeTabId:a}}let r={...a,...t};u[n]=f.grid,d[n]=f.focusedPanelId,e({currentProject:n,panels:r,grid:f.grid,focusedPanelId:f.focusedPanelId,projectGrids:u,projectFocused:d})}else{let t=r(),i=[[t.id]],o={...a,[t.id]:t};u[n]=i,d[n]=t.id,p(n,{panels:{[t.id]:t},grid:i,focusedPanelId:t.id}),e({currentProject:n,panels:o,grid:i,focusedPanelId:t.id,projectGrids:u,projectFocused:d})}},reloadProject:n=>{let{projectGrids:r,projectFocused:i,panels:a}=t(),o={...r},s={...i};delete o[n],delete s[n];let c=r[n],l=c?new Set(c.flat()):new Set,u={...a};for(let e of l)delete u[e];e({projectGrids:o,projectFocused:s,panels:u,currentProject:null}),t().switchProject(n)},setFocusedPanel:n=>{t().panels[n]&&e({focusedPanelId:n})},openTab:(r,i)=>{let a=t().isMobile(),o=a?t().grid[0]?.[0]??l(i):l(i);if(!t().panels[o])return``;if(r.type===`terminal`&&!r.metadata?.terminalIndex){let e=Object.values(t().panels).flatMap(e=>e.tabs).filter(e=>e.type===`terminal`).map(e=>{let t=e.id.match(/^terminal:(\d+)/);return t?parseInt(t[1],10):0}),n=e.length>0?Math.max(...e)+1:1;r={...r,metadata:{...r.metadata,terminalIndex:n}}}let s=c(r.type,r.metadata);if(b.has(r.type))for(let r of Object.values(t().panels)){let t=r.tabs.find(e=>e.id===s);if(t)return e(e=>({focusedPanelId:r.id,panels:{...e.panels,[r.id]:{...r,activeTabId:t.id,tabHistory:S(r.tabHistory,t.id)}}})),n(),t.id}if(a)for(let r of t().grid.flat()){let i=t().panels[r];if(!i)continue;let a=i.tabs.find(e=>e.id===s||e.id.startsWith(`${s}@`));if(a)return e(e=>({focusedPanelId:i.id,panels:{...e.panels,[i.id]:{...i,activeTabId:a.id,tabHistory:S(i.tabHistory,a.id)}}})),n(),a.id}let u=t().panels[o],d=u.tabs.find(e=>e.id===s);if(d)return e(e=>({panels:{...e.panels,[o]:{...u,activeTabId:d.id,tabHistory:S(u.tabHistory,d.id)}}})),n(),d.id;let f=Object.values(t().panels).some(e=>e.id!==o&&e.tabs.some(e=>e.id===s))?`${s}@${o}`:s,p={...r,id:f};return e(e=>{let t=e.panels[o];return{focusedPanelId:o,panels:{...e.panels,[o]:{...t,tabs:[...t.tabs,p],activeTabId:f,tabHistory:S(t.tabHistory,f)}}}}),n(),f},closeTab:(r,i)=>{let o=i?t().panels[i]:s(r);if(!o)return;let c=o.id;e(e=>{let t=e.panels[c],n=t.tabs.filter(e=>e.id!==r),i=t.tabHistory.filter(e=>e!==r),o=t.activeTabId;if(t.activeTabId===r){let e=i.length>0?i[i.length-1]:null;o=e&&n.some(t=>t.id===e)?e:n[n.length-1]?.id??null}let s=e.grid.flat().length;if(n.length===0&&s>1){let{[c]:t,...n}=e.panels;return{panels:n,grid:a(e.grid,c),focusedPanelId:e.focusedPanelId===c?Object.keys(n)[0]:e.focusedPanelId}}return{panels:{...e.panels,[c]:{...t,tabs:n,activeTabId:o,tabHistory:i}}}}),n()},setActiveTab:(r,i)=>{let a=i?t().panels[i]:s(r);if(!a)return;let o=a.id;e(e=>{let t=e.panels[o];return{focusedPanelId:o,panels:{...e.panels,[o]:{...t,activeTabId:r,tabHistory:S(t.tabHistory,r)}}}}),n()},updateTab:(t,r)=>{let i=s(t);i&&(e(e=>({panels:{...e.panels,[i.id]:{...i,tabs:i.tabs.map(e=>e.id===t?{...e,...r}:e)}}})),n())},reorderTab:(r,i,a)=>{let o=t().panels[i];if(!o)return;let s=o.tabs.findIndex(e=>e.id===r);if(s===-1||s===a)return;let c=[...o.tabs],[l]=c.splice(s,1);c.splice(a,0,l),e(e=>({panels:{...e.panels,[i]:{...o,tabs:c}}})),n()},moveTab:(r,i,o,s)=>{if(i===o)return;let c=t().panels[i],l=t().panels[o];if(!c||!l)return;let u=c.tabs.find(e=>e.id===r);if(!u)return;let d=c.tabs.filter(e=>e.id!==r),f=c.tabHistory.filter(e=>e!==r),p=c.activeTabId===r?f[f.length-1]??d[d.length-1]?.id??null:c.activeTabId,m=[...l.tabs];s===void 0?m.push(u):m.splice(s,0,u),e(e=>{let t=e.grid.flat().length;if(d.length===0&&t>1){let{[i]:t,...n}=e.panels;return{panels:{...n,[o]:{...l,tabs:m,activeTabId:r,tabHistory:S(l.tabHistory,r)}},grid:a(e.grid,i),focusedPanelId:o}}return{focusedPanelId:o,panels:{...e.panels,[i]:{...c,tabs:d,activeTabId:p,tabHistory:f},[o]:{...l,tabs:m,activeTabId:r,tabHistory:S(l.tabHistory,r)}}}}),n()},splitPanel:(s,c,l,u)=>{let{grid:d,panels:f}=t(),p=t().isMobile(),m=f[l];if(!m)return!1;let h=m.tabs.find(e=>e.id===c);if(!h)return!1;let g=o(d,u??l);if(!g)return!1;let _=s===`left`||s===`right`,v=s===`up`||s===`down`;if(_&&(d[g.row]?.length??0)>=i(p)||v&&d.length>=3)return!1;let y=r([h],h.id);y.tabHistory=[h.id];let b=m.tabs.filter(e=>e.id!==c),x=m.tabHistory.filter(e=>e!==c),S=m.activeTabId===c?x[x.length-1]??b[b.length-1]?.id??null:m.activeTabId,C;if(_)C=d.map((e,t)=>{if(t!==g.row)return e;let n=[...e],r=s===`right`?g.col+1:g.col;return n.splice(r,0,y.id),n});else{C=[...d];let e=s===`down`?g.row+1:g.row;C.splice(e,0,[y.id])}return e(e=>{let t=e.grid.flat().length,n={...e.panels,[y.id]:y};if(b.length===0&&t>1){let{[l]:e,...t}=n;n=t,C=a(C,l)}else n[l]={...m,tabs:b,activeTabId:S,tabHistory:x};return{panels:n,grid:C,focusedPanelId:y.id}}),n(),!0},closePanel:r=>{let{panels:i,grid:s}=t();if(s.flat().length<=1)return;let c=i[r];if(!c)return;o(s,r);let l=s.flat(),u=l.indexOf(r),d=u>0?l[u-1]:l[1],f=i[d];f&&(e(e=>{let{[r]:t,...n}=e.panels,i=[...f.tabs,...c.tabs],o=f.activeTabId??c.activeTabId;return{panels:{...n,[d]:{...f,tabs:i,activeTabId:o,tabHistory:[...f.tabHistory,...c.tabHistory]}},grid:a(e.grid,r),focusedPanelId:d}}),n())},getPanelForTab:e=>s(e),isMobile:()=>typeof window<`u`&&window.innerWidth<768}}),T=e()(()=>({tabs:[],activeTabId:null,tabHistory:[],currentProject:null,switchProject:e=>{w.getState().switchProject(e),E()},openTab:e=>{let t=w.getState().openTab(e);return E(),t},closeTab:e=>{w.getState().closeTab(e),E()},setActiveTab:e=>{w.getState().setActiveTab(e),E()},updateTab:(e,t)=>{w.getState().updateTab(e,t),E()},openNewFile:()=>{let e=w.getState(),t=s(e.panels),n=e.openTab({type:`editor`,title:`Untitled-${t}`,projectId:null,metadata:{isUntitled:!0,untitledNumber:t},closable:!0});return E(),n}}));function E(){let e=w.getState(),t=e.panels[e.focusedPanelId];T.setState({tabs:t?.tabs??[],activeTabId:t?.activeTabId??null,tabHistory:t?.tabHistory??[],currentProject:e.currentProject})}w.subscribe(()=>E());export{o as a,h as i,w as n,i as o,r,v as s,T as t};
|
|
1
|
+
import{t as e}from"./react-DMIOAtcX.js";import{r as t}from"./utils-CQux7CsO.js";function n(){return`panel-${t()}`}function r(e=[],t=null){return{id:n(),tabs:e,activeTabId:t,tabHistory:t?[t]:[]}}function i(e){return e?1:3}function a(e,t){return e.map(e=>e.filter(e=>e!==t)).filter(e=>e.length>0)}function o(e,t){for(let n=0;n<e.length;n++){let r=e[n].indexOf(t);if(r!==-1)return{row:n,col:r}}return null}function s(e){let t=0;for(let n of Object.values(e))for(let e of n.tabs){let n=e.id.match(/^editor:untitled-(\d+)$/);n&&(t=Math.max(t,Number(n[1])))}return t+1}function c(e,n){switch(e){case`editor`:return n?.viewerKey?`editor:viewer:${n.viewerKey}`:n?.isUntitled?`editor:untitled-${n.untitledNumber??1}`:`editor:${n?.filePath??`untitled`}`;case`chat`:return`chat:${n?.providerId??`default`}/${n?.sessionId??t()}`;case`terminal`:return`terminal:${n?.terminalIndex??1}`;case`database`:return`database:${n?.connectionId??`default`}:${n?.tableName??``}`;case`sqlite`:return`sqlite:${n?.filePath??`default`}`;case`postgres`:return`postgres:${n?.connectionId??`default`}:${n?.tableName??``}`;case`extension`:return`extension:${String(n?.viewType??`unknown`).replace(/\.view$/,``)}`;case`git-diff`:return`git-diff:${n?.filePath??`unknown`}`;case`conflict-editor`:return`conflict-editor:${n?.filePath??`unknown`}`;case`settings`:return`settings`;case`ports`:return`ports`;default:return`${e}:${t()}`}}function l(e){let t={...e,panels:{...e.panels}};for(let[e,n]of Object.entries(t.panels)){let r=n.tabs.map(e=>{if(e.id.startsWith(`tab-`)){let t=c(e.type,e.metadata);return{...e,id:t}}return e}),i=new Map;n.tabs.forEach((e,t)=>{e.id!==r[t].id&&i.set(e.id,r[t].id)});let a=i.get(n.activeTabId??``)??n.activeTabId,o=n.tabHistory.map(e=>i.get(e)??e);t.panels[e]={...n,tabs:r,activeTabId:a,tabHistory:o}}return t}var u=`ppm-panels-`,d=`ppm-tabs-`;function f(e){return`${u}${e}`}function p(e,t){try{let n={...t,updatedAt:new Date().toISOString()};localStorage.setItem(f(e),JSON.stringify(n)),e!==`__global__`&&_(e,t)}catch{}}function m(e){try{let t=localStorage.getItem(f(e));if(t)return l(JSON.parse(t))}catch{}return y(e)}async function h(e){if(e===`__global__`)return null;try{let t={},n=localStorage.getItem(`ppm-auth-token`);n&&(t.Authorization=`Bearer ${n}`);let r=await fetch(`/api/project/${encodeURIComponent(e)}/workspace`,{headers:t});if(!r.ok)return null;let i=await r.json();return!i.ok||!i.data?null:{...i.data.layout,updatedAt:i.data.updatedAt}}catch{return null}}var g=new Map;function _(e,t){let n=g.get(e);n&&clearTimeout(n),g.set(e,setTimeout(async()=>{g.delete(e);try{let n={"Content-Type":`application/json`},r=localStorage.getItem(`ppm-auth-token`);r&&(n.Authorization=`Bearer ${r}`);let i=await fetch(`/api/project/${encodeURIComponent(e)}/workspace`,{method:`PUT`,headers:n,body:JSON.stringify({layout:t})});if(i.ok){let t=await i.json();if(t.data?.updatedAt){let n=`${u}${e}`,r=localStorage.getItem(n);if(r){let e=JSON.parse(r);e.updatedAt=t.data.updatedAt,localStorage.setItem(n,JSON.stringify(e))}}}}catch{}},1500))}function v(e,t){if(!e&&!t)return null;if(!e)return t;if(!t)return e;let n=new Date(e.updatedAt).getTime();return new Date(t.updatedAt).getTime()>=n?t:e}function y(e){try{let t=localStorage.getItem(`${d}${e}`);if(!t)return null;let n=JSON.parse(t);if(!n.tabs?.length)return null;let i=r(n.tabs,n.activeTabId),a={panels:{[i.id]:i},grid:[[i.id]],focusedPanelId:i.id};return p(e,a),localStorage.removeItem(`${d}${e}`),a}catch{return null}}var b=new Set([`settings`]),x=new Set([`projects`,`git-status`,`git-graph`]);function S(e,t){let n=e.filter(e=>e!==t);return n.push(t),n.length>50&&n.shift(),n}function C(){let e=r();return{panels:{[e.id]:e},grid:[[e.id]],focusedPanelId:e.id}}var w=e()((e,t)=>{function n(){let{currentProject:e,panels:n,grid:r,focusedPanelId:i}=t();if(!e)return;let a=new Set(r.flat()),o={};for(let[e,t]of Object.entries(n))a.has(e)&&(o[e]=t);p(e,{panels:o,grid:r,focusedPanelId:i})}function s(e){return Object.values(t().panels).find(t=>t.tabs.some(t=>t.id===e))}function l(e){return e??t().focusedPanelId}return{...C(),currentProject:null,projectGrids:{},projectFocused:{},switchProject:n=>{let{currentProject:i,panels:a,grid:o,focusedPanelId:s,projectGrids:c,projectFocused:l}=t();if(i===n)return;let u={...c},d={...l};if(i){u[i]=o,d[i]=s;let e=new Set(o.flat()),t={};for(let[n,r]of Object.entries(a))e.has(n)&&(t[n]=r);p(i,{panels:t,grid:o,focusedPanelId:s})}if(u[n]){let t=u[n];e({currentProject:n,grid:t,focusedPanelId:d[n]??t[0]?.[0]??``,projectGrids:u,projectFocused:d});return}let f=m(n);if(f&&Object.keys(f.panels).length>0){let t={};for(let[e,n]of Object.entries(f.panels)){let r=n.tabs.filter(e=>!x.has(e.type)),i=n.tabHistory.filter(e=>r.some(t=>t.id===e)),a=n.activeTabId&&r.some(e=>e.id===n.activeTabId)?n.activeTabId:i[i.length-1]??r[0]?.id??null;t[e]={...n,tabs:r,tabHistory:i,activeTabId:a}}let r={...a,...t};u[n]=f.grid,d[n]=f.focusedPanelId,e({currentProject:n,panels:r,grid:f.grid,focusedPanelId:f.focusedPanelId,projectGrids:u,projectFocused:d})}else{let t=r(),i=[[t.id]],o={...a,[t.id]:t};u[n]=i,d[n]=t.id,p(n,{panels:{[t.id]:t},grid:i,focusedPanelId:t.id}),e({currentProject:n,panels:o,grid:i,focusedPanelId:t.id,projectGrids:u,projectFocused:d})}},reloadProject:n=>{let{projectGrids:r,projectFocused:i,panels:a}=t(),o={...r},s={...i};delete o[n],delete s[n];let c=r[n],l=c?new Set(c.flat()):new Set,u={...a};for(let e of l)delete u[e];e({projectGrids:o,projectFocused:s,panels:u,currentProject:null}),t().switchProject(n)},setFocusedPanel:n=>{t().panels[n]&&e({focusedPanelId:n})},openTab:(r,i)=>{let a=t().isMobile(),o=a?t().grid[0]?.[0]??l(i):l(i);if(!t().panels[o])return``;if(r.type===`terminal`&&!r.metadata?.terminalIndex){let e=Object.values(t().panels).flatMap(e=>e.tabs).filter(e=>e.type===`terminal`).map(e=>{let t=e.id.match(/^terminal:(\d+)/);return t?parseInt(t[1],10):0}),n=e.length>0?Math.max(...e)+1:1;r={...r,metadata:{...r.metadata,terminalIndex:n}}}let s=c(r.type,r.metadata);if(b.has(r.type))for(let r of Object.values(t().panels)){let t=r.tabs.find(e=>e.id===s);if(t)return e(e=>({focusedPanelId:r.id,panels:{...e.panels,[r.id]:{...r,activeTabId:t.id,tabHistory:S(r.tabHistory,t.id)}}})),n(),t.id}if(a)for(let r of t().grid.flat()){let i=t().panels[r];if(!i)continue;let a=i.tabs.find(e=>e.id===s||e.id.startsWith(`${s}@`));if(a)return e(e=>({focusedPanelId:i.id,panels:{...e.panels,[i.id]:{...i,activeTabId:a.id,tabHistory:S(i.tabHistory,a.id)}}})),n(),a.id}let u=t().panels[o],d=u.tabs.find(e=>e.id===s);if(d)return e(e=>({panels:{...e.panels,[o]:{...u,activeTabId:d.id,tabHistory:S(u.tabHistory,d.id)}}})),n(),d.id;let f=Object.values(t().panels).some(e=>e.id!==o&&e.tabs.some(e=>e.id===s))?`${s}@${o}`:s,p={...r,id:f};return e(e=>{let t=e.panels[o];return{focusedPanelId:o,panels:{...e.panels,[o]:{...t,tabs:[...t.tabs,p],activeTabId:f,tabHistory:S(t.tabHistory,f)}}}}),n(),f},closeTab:(r,i)=>{let o=i?t().panels[i]:s(r);if(!o)return;let c=o.id;e(e=>{let t=e.panels[c],n=t.tabs.filter(e=>e.id!==r),i=t.tabHistory.filter(e=>e!==r),o=t.activeTabId;if(t.activeTabId===r){let e=i.length>0?i[i.length-1]:null;o=e&&n.some(t=>t.id===e)?e:n[n.length-1]?.id??null}let s=e.grid.flat().length;if(n.length===0&&s>1){let{[c]:t,...n}=e.panels;return{panels:n,grid:a(e.grid,c),focusedPanelId:e.focusedPanelId===c?Object.keys(n)[0]:e.focusedPanelId}}return{panels:{...e.panels,[c]:{...t,tabs:n,activeTabId:o,tabHistory:i}}}}),n()},setActiveTab:(r,i)=>{let a=i?t().panels[i]:s(r);if(!a)return;let o=a.id;e(e=>{let t=e.panels[o];return{focusedPanelId:o,panels:{...e.panels,[o]:{...t,activeTabId:r,tabHistory:S(t.tabHistory,r)}}}}),n()},updateTab:(t,r)=>{let i=s(t);i&&(e(e=>({panels:{...e.panels,[i.id]:{...i,tabs:i.tabs.map(e=>e.id===t?{...e,...r}:e)}}})),n())},reorderTab:(r,i,a)=>{let o=t().panels[i];if(!o)return;let s=o.tabs.findIndex(e=>e.id===r);if(s===-1||s===a)return;let c=[...o.tabs],[l]=c.splice(s,1);c.splice(a,0,l),e(e=>({panels:{...e.panels,[i]:{...o,tabs:c}}})),n()},moveTab:(r,i,o,s)=>{if(i===o)return;let c=t().panels[i],l=t().panels[o];if(!c||!l)return;let u=c.tabs.find(e=>e.id===r);if(!u)return;let d=c.tabs.filter(e=>e.id!==r),f=c.tabHistory.filter(e=>e!==r),p=c.activeTabId===r?f[f.length-1]??d[d.length-1]?.id??null:c.activeTabId,m=[...l.tabs];s===void 0?m.push(u):m.splice(s,0,u),e(e=>{let t=e.grid.flat().length;if(d.length===0&&t>1){let{[i]:t,...n}=e.panels;return{panels:{...n,[o]:{...l,tabs:m,activeTabId:r,tabHistory:S(l.tabHistory,r)}},grid:a(e.grid,i),focusedPanelId:o}}return{focusedPanelId:o,panels:{...e.panels,[i]:{...c,tabs:d,activeTabId:p,tabHistory:f},[o]:{...l,tabs:m,activeTabId:r,tabHistory:S(l.tabHistory,r)}}}}),n()},splitPanel:(s,c,l,u)=>{let{grid:d,panels:f}=t(),p=t().isMobile(),m=f[l];if(!m)return!1;let h=m.tabs.find(e=>e.id===c);if(!h)return!1;let g=o(d,u??l);if(!g)return!1;let _=s===`left`||s===`right`,v=s===`up`||s===`down`;if(_&&(d[g.row]?.length??0)>=i(p)||v&&d.length>=3)return!1;let y=r([h],h.id);y.tabHistory=[h.id];let b=m.tabs.filter(e=>e.id!==c),x=m.tabHistory.filter(e=>e!==c),S=m.activeTabId===c?x[x.length-1]??b[b.length-1]?.id??null:m.activeTabId,C;if(_)C=d.map((e,t)=>{if(t!==g.row)return e;let n=[...e],r=s===`right`?g.col+1:g.col;return n.splice(r,0,y.id),n});else{C=[...d];let e=s===`down`?g.row+1:g.row;C.splice(e,0,[y.id])}return e(e=>{let t=e.grid.flat().length,n={...e.panels,[y.id]:y};if(b.length===0&&t>1){let{[l]:e,...t}=n;n=t,C=a(C,l)}else n[l]={...m,tabs:b,activeTabId:S,tabHistory:x};return{panels:n,grid:C,focusedPanelId:y.id}}),n(),!0},closePanel:r=>{let{panels:i,grid:s}=t();if(s.flat().length<=1)return;let c=i[r];if(!c)return;o(s,r);let l=s.flat(),u=l.indexOf(r),d=u>0?l[u-1]:l[1],f=i[d];f&&(e(e=>{let{[r]:t,...n}=e.panels,i=[...f.tabs,...c.tabs],o=f.activeTabId??c.activeTabId;return{panels:{...n,[d]:{...f,tabs:i,activeTabId:o,tabHistory:[...f.tabHistory,...c.tabHistory]}},grid:a(e.grid,r),focusedPanelId:d}}),n())},getPanelForTab:e=>s(e),isMobile:()=>typeof window<`u`&&window.innerWidth<768}}),T=e()(()=>({tabs:[],activeTabId:null,tabHistory:[],currentProject:null,switchProject:e=>{w.getState().switchProject(e),E()},openTab:e=>{let t=w.getState().openTab(e);return E(),t},closeTab:e=>{w.getState().closeTab(e),E()},setActiveTab:e=>{w.getState().setActiveTab(e),E()},updateTab:(e,t)=>{w.getState().updateTab(e,t),E()},openNewFile:()=>{let e=w.getState(),t=s(e.panels),n=e.openTab({type:`editor`,title:`Untitled-${t}`,projectId:null,metadata:{isUntitled:!0,untitledNumber:t},closable:!0});return E(),n}}));function E(){let e=w.getState(),t=e.panels[e.focusedPanelId];T.setState({tabs:t?.tabs??[],activeTabId:t?.activeTabId??null,tabHistory:t?.tabHistory??[],currentProject:e.currentProject})}w.subscribe(()=>E());export{o as a,h as i,w as n,i as o,r,v as s,T as t};
|
|
2
|
+
//# sourceMappingURL=tab-store-S9w6U5gm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tab-store-S9w6U5gm.js","names":[],"sources":["../../../src/web/stores/panel-utils.ts","../../../src/web/stores/panel-store.ts","../../../src/web/stores/tab-store.ts"],"sourcesContent":["import { randomId } from \"@/lib/utils\";\nimport type { Tab, TabType } from \"./tab-store\";\n\n// ---------------------------------------------------------------------------\n// Panel types\n// ---------------------------------------------------------------------------\nexport interface Panel {\n id: string;\n tabs: Tab[];\n activeTabId: string | null;\n tabHistory: string[];\n}\n\nexport interface PanelLayout {\n panels: Record<string, Panel>;\n /** grid[row][col] = panelId */\n grid: string[][];\n focusedPanelId: string;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\nexport function generatePanelId(): string {\n return `panel-${randomId()}`;\n}\n\nexport function createPanel(tabs: Tab[] = [], activeTabId: string | null = null): Panel {\n return {\n id: generatePanelId(),\n tabs,\n activeTabId,\n tabHistory: activeTabId ? [activeTabId] : [],\n };\n}\n\n/** Max columns: 3 desktop, 1 mobile */\nexport function maxColumns(isMobile: boolean): number {\n return isMobile ? 1 : 3;\n}\n\n/** Max rows in the grid */\nexport const MAX_ROWS = 3;\n\n// ---------------------------------------------------------------------------\n// Grid manipulation\n// ---------------------------------------------------------------------------\n/** Add a new row to the grid (outer array) */\nexport function gridAddRow(grid: string[][], panelId: string): string[][] {\n return [...grid, [panelId]];\n}\n\n/** Add a column within an existing row (inner array) */\nexport function gridAddColumn(grid: string[][], rowIndex: number, panelId: string): string[][] {\n return grid.map((row, i) => (i === rowIndex ? [...row, panelId] : row));\n}\n\nexport function gridRemovePanel(grid: string[][], panelId: string): string[][] {\n return grid\n .map((col) => col.filter((id) => id !== panelId))\n .filter((col) => col.length > 0);\n}\n\nexport function findPanelPosition(grid: string[][], panelId: string): { row: number; col: number } | null {\n for (let r = 0; r < grid.length; r++) {\n const c = grid[r]!.indexOf(panelId);\n if (c !== -1) return { row: r, col: c };\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Deterministic tab IDs\n// ---------------------------------------------------------------------------\n\n/** Get next untitled number by scanning all panels */\nexport function getNextUntitledNumber(panels: Record<string, Panel>): number {\n let max = 0;\n for (const panel of Object.values(panels)) {\n for (const tab of panel.tabs) {\n const match = tab.id.match(/^editor:untitled-(\\d+)$/);\n if (match) max = Math.max(max, Number(match[1]));\n }\n }\n return max + 1;\n}\n\n/** Derive deterministic tab ID from type + metadata */\nexport function deriveTabId(type: TabType, metadata?: Record<string, unknown>): string {\n switch (type) {\n case \"editor\":\n if (metadata?.viewerKey) return `editor:viewer:${metadata.viewerKey}`;\n if (metadata?.isUntitled) return `editor:untitled-${metadata.untitledNumber ?? 1}`;\n return `editor:${metadata?.filePath ?? \"untitled\"}`;\n case \"chat\": {\n const provider = metadata?.providerId ?? \"default\";\n return `chat:${provider}/${metadata?.sessionId ?? randomId()}`;\n }\n case \"terminal\":\n return `terminal:${metadata?.terminalIndex ?? 1}`;\n case \"database\":\n return `database:${metadata?.connectionId ?? \"default\"}:${metadata?.tableName ?? \"\"}`;\n case \"sqlite\":\n return `sqlite:${metadata?.filePath ?? \"default\"}`;\n case \"postgres\":\n return `postgres:${metadata?.connectionId ?? \"default\"}:${metadata?.tableName ?? \"\"}`;\n case \"extension\": {\n const vt = String(metadata?.viewType ?? \"unknown\").replace(/\\.view$/, \"\");\n return `extension:${vt}`;\n }\n case \"git-diff\":\n return `git-diff:${metadata?.filePath ?? \"unknown\"}`;\n case \"conflict-editor\":\n return `conflict-editor:${metadata?.filePath ?? \"unknown\"}`;\n case \"settings\":\n return \"settings\";\n case \"ports\":\n return \"ports\";\n default:\n return `${type}:${randomId()}`;\n }\n}\n\n/** Migrate old random tab IDs to deterministic IDs */\nexport function migrateTabIds(layout: PanelLayout): PanelLayout {\n const migrated = { ...layout, panels: { ...layout.panels } };\n for (const [panelId, panel] of Object.entries(migrated.panels)) {\n const newTabs = panel.tabs.map((tab) => {\n if (tab.id.startsWith(\"tab-\")) {\n const newId = deriveTabId(tab.type, tab.metadata);\n return { ...tab, id: newId };\n }\n return tab;\n });\n const idMap = new Map<string, string>();\n panel.tabs.forEach((old, i) => {\n if (old.id !== newTabs[i]!.id) idMap.set(old.id, newTabs[i]!.id);\n });\n const newActive = idMap.get(panel.activeTabId ?? \"\") ?? panel.activeTabId;\n const newHistory = panel.tabHistory.map((h) => idMap.get(h) ?? h);\n migrated.panels[panelId] = { ...panel, tabs: newTabs, activeTabId: newActive, tabHistory: newHistory };\n }\n return migrated;\n}\n\n// ---------------------------------------------------------------------------\n// Persistence\n// ---------------------------------------------------------------------------\nconst STORAGE_PREFIX = \"ppm-panels-\";\nconst OLD_STORAGE_PREFIX = \"ppm-tabs-\";\n\nfunction storageKey(projectName: string): string {\n return `${STORAGE_PREFIX}${projectName}`;\n}\n\nexport function savePanelLayout(projectName: string, layout: PanelLayout): void {\n try {\n const withTimestamp = { ...layout, updatedAt: new Date().toISOString() };\n localStorage.setItem(storageKey(projectName), JSON.stringify(withTimestamp));\n // Debounced server sync — skip virtual __global__ project (not a real server project)\n if (projectName !== \"__global__\") syncWorkspaceToServer(projectName, layout);\n } catch { /* ignore */ }\n}\n\nexport function loadPanelLayout(projectName: string): PanelLayout | null {\n try {\n const raw = localStorage.getItem(storageKey(projectName));\n if (raw) {\n const layout = JSON.parse(raw) as PanelLayout;\n return migrateTabIds(layout);\n }\n } catch { /* ignore */ }\n\n // Migrate from old tab-store format\n return migrateOldTabStore(projectName);\n}\n\n// ---------------------------------------------------------------------------\n// Server sync\n// ---------------------------------------------------------------------------\n\nexport interface PanelLayoutWithTimestamp extends PanelLayout {\n updatedAt: string;\n}\n\n/** Fetch workspace from server */\nexport async function fetchWorkspaceFromServer(\n projectName: string,\n): Promise<PanelLayoutWithTimestamp | null> {\n if (projectName === \"__global__\") return null;\n try {\n const headers: Record<string, string> = {};\n const token = localStorage.getItem(\"ppm-auth-token\");\n if (token) headers[\"Authorization\"] = `Bearer ${token}`;\n\n const res = await fetch(`/api/project/${encodeURIComponent(projectName)}/workspace`, { headers });\n if (!res.ok) return null;\n const json = await res.json();\n if (!json.ok || !json.data) return null;\n return { ...json.data.layout, updatedAt: json.data.updatedAt };\n } catch {\n return null;\n }\n}\n\n/** Save workspace to server (debounced per project) */\nconst syncTimers = new Map<string, ReturnType<typeof setTimeout>>();\n\nfunction syncWorkspaceToServer(projectName: string, layout: PanelLayout): void {\n const existing = syncTimers.get(projectName);\n if (existing) clearTimeout(existing);\n\n syncTimers.set(projectName, setTimeout(async () => {\n syncTimers.delete(projectName);\n try {\n const headers: Record<string, string> = { \"Content-Type\": \"application/json\" };\n const token = localStorage.getItem(\"ppm-auth-token\");\n if (token) headers[\"Authorization\"] = `Bearer ${token}`;\n\n const res = await fetch(`/api/project/${encodeURIComponent(projectName)}/workspace`, {\n method: \"PUT\",\n headers,\n body: JSON.stringify({ layout }),\n });\n if (res.ok) {\n const json = await res.json();\n if (json.data?.updatedAt) {\n const key = `${STORAGE_PREFIX}${projectName}`;\n const raw = localStorage.getItem(key);\n if (raw) {\n const local = JSON.parse(raw);\n local.updatedAt = json.data.updatedAt;\n localStorage.setItem(key, JSON.stringify(local));\n }\n }\n }\n } catch { /* silent fail — localStorage is still the cache */ }\n }, 1500));\n}\n\n/** Compare local vs server timestamps, return newer layout */\nexport function resolveWorkspaceConflict(\n local: PanelLayoutWithTimestamp | null,\n server: PanelLayoutWithTimestamp | null,\n): PanelLayoutWithTimestamp | null {\n if (!local && !server) return null;\n if (!local) return server!;\n if (!server) return local;\n\n const localTime = new Date(local.updatedAt).getTime();\n const serverTime = new Date(server.updatedAt).getTime();\n return serverTime >= localTime ? server : local;\n}\n\n// ---------------------------------------------------------------------------\n// Old format migration\n// ---------------------------------------------------------------------------\n\nfunction migrateOldTabStore(projectName: string): PanelLayout | null {\n try {\n const raw = localStorage.getItem(`${OLD_STORAGE_PREFIX}${projectName}`);\n if (!raw) return null;\n const old = JSON.parse(raw) as { tabs: Tab[]; activeTabId: string | null };\n if (!old.tabs?.length) return null;\n\n const panel = createPanel(old.tabs, old.activeTabId);\n const layout: PanelLayout = {\n panels: { [panel.id]: panel },\n grid: [[panel.id]],\n focusedPanelId: panel.id,\n };\n // Save new format and clean old\n savePanelLayout(projectName, layout);\n localStorage.removeItem(`${OLD_STORAGE_PREFIX}${projectName}`);\n return layout;\n } catch {\n return null;\n }\n}\n","import { create } from \"zustand\";\nimport type { Tab, TabType } from \"./tab-store\";\nimport {\n type Panel,\n type PanelLayout,\n createPanel,\n gridAddColumn,\n gridAddRow,\n gridRemovePanel,\n findPanelPosition,\n maxColumns,\n MAX_ROWS,\n savePanelLayout,\n loadPanelLayout,\n deriveTabId,\n} from \"./panel-utils\";\n\n/** Tab types that can only have 1 instance per project */\nconst SINGLETON_TYPES = new Set<TabType>([\"settings\"]);\n\n/** Tab types removed in a prior version — filter them out when loading persisted state */\nconst OBSOLETE_TAB_TYPES = new Set([\"projects\", \"git-status\", \"git-graph\"]);\n\nfunction pushHistory(history: string[], id: string): string[] {\n const filtered = history.filter((h) => h !== id);\n filtered.push(id);\n if (filtered.length > 50) filtered.shift();\n return filtered;\n}\n\n// ---------------------------------------------------------------------------\n// Store interface\n// ---------------------------------------------------------------------------\nexport interface PanelStore {\n panels: Record<string, Panel>;\n grid: string[][];\n focusedPanelId: string;\n currentProject: string | null;\n\n /** Keep-alive: per-project grid snapshots (for hidden workspaces) */\n projectGrids: Record<string, string[][]>;\n projectFocused: Record<string, string>;\n\n // Project lifecycle\n switchProject: (projectName: string) => void;\n reloadProject: (projectName: string) => void;\n\n // Panel focus\n setFocusedPanel: (panelId: string) => void;\n\n // Tab operations (operate on focused panel by default)\n openTab: (tab: Omit<Tab, \"id\">, panelId?: string) => string;\n closeTab: (tabId: string, panelId?: string) => void;\n setActiveTab: (tabId: string, panelId?: string) => void;\n updateTab: (tabId: string, updates: Partial<Omit<Tab, \"id\">>) => void;\n\n // Panel operations\n reorderTab: (tabId: string, panelId: string, newIndex: number) => void;\n moveTab: (tabId: string, fromPanelId: string, toPanelId: string, insertIndex?: number) => void;\n splitPanel: (direction: \"left\" | \"right\" | \"up\" | \"down\", tabId: string, sourcePanelId: string, targetPanelId?: string) => boolean;\n closePanel: (panelId: string) => void;\n\n // Helpers\n getPanelForTab: (tabId: string) => Panel | undefined;\n isMobile: () => boolean;\n}\n\nfunction defaultLayout(): { panels: Record<string, Panel>; grid: string[][]; focusedPanelId: string } {\n const panel = createPanel();\n return { panels: { [panel.id]: panel }, grid: [[panel.id]], focusedPanelId: panel.id };\n}\n\n// ---------------------------------------------------------------------------\n// Store\n// ---------------------------------------------------------------------------\nexport const usePanelStore = create<PanelStore>()((set, get) => {\n /** Save only the active project's panels to localStorage */\n function persist() {\n const { currentProject, panels, grid, focusedPanelId } = get();\n if (!currentProject) return;\n const panelIds = new Set(grid.flat());\n const projectPanels: Record<string, Panel> = {};\n for (const [id, p] of Object.entries(panels)) {\n if (panelIds.has(id)) projectPanels[id] = p;\n }\n savePanelLayout(currentProject, { panels: projectPanels, grid, focusedPanelId });\n }\n\n function findPanel(tabId: string): Panel | undefined {\n return Object.values(get().panels).find((p) => p.tabs.some((t) => t.id === tabId));\n }\n\n function resolvePanel(panelId?: string): string {\n return panelId ?? get().focusedPanelId;\n }\n\n return {\n ...defaultLayout(),\n currentProject: null,\n projectGrids: {},\n projectFocused: {},\n\n switchProject: (projectName) => {\n const { currentProject, panels, grid, focusedPanelId, projectGrids, projectFocused } = get();\n\n // No-op if same project\n if (currentProject === projectName) return;\n\n // Snapshot current project's state\n const newProjectGrids = { ...projectGrids };\n const newProjectFocused = { ...projectFocused };\n\n if (currentProject) {\n newProjectGrids[currentProject] = grid;\n newProjectFocused[currentProject] = focusedPanelId;\n // Persist to localStorage\n const panelIds = new Set(grid.flat());\n const currentPanels: Record<string, Panel> = {};\n for (const [id, p] of Object.entries(panels)) {\n if (panelIds.has(id)) currentPanels[id] = p;\n }\n savePanelLayout(currentProject, { panels: currentPanels, grid, focusedPanelId });\n }\n\n // Already in memory → restore from snapshot (no localStorage read)\n if (newProjectGrids[projectName]) {\n const restoredGrid = newProjectGrids[projectName]!;\n const restoredFocused = newProjectFocused[projectName] ?? restoredGrid[0]?.[0] ?? \"\";\n set({\n currentProject: projectName,\n grid: restoredGrid,\n focusedPanelId: restoredFocused,\n projectGrids: newProjectGrids,\n projectFocused: newProjectFocused,\n });\n return;\n }\n\n // Load from localStorage\n const loaded = loadPanelLayout(projectName);\n if (loaded && Object.keys(loaded.panels).length > 0) {\n // Migrate: remove obsolete tab types\n const migratedPanels: typeof loaded.panels = {};\n for (const [pid, panel] of Object.entries(loaded.panels)) {\n const filteredTabs = panel.tabs.filter((t) => !OBSOLETE_TAB_TYPES.has(t.type));\n const filteredHistory = panel.tabHistory.filter(\n (id) => filteredTabs.some((t) => t.id === id),\n );\n const activeTabId = panel.activeTabId && filteredTabs.some((t) => t.id === panel.activeTabId)\n ? panel.activeTabId\n : (filteredHistory[filteredHistory.length - 1] ?? filteredTabs[0]?.id ?? null);\n migratedPanels[pid] = { ...panel, tabs: filteredTabs, tabHistory: filteredHistory, activeTabId };\n }\n\n // Merge into flat panels map (keep-alive: old panels stay)\n const mergedPanels = { ...panels, ...migratedPanels };\n newProjectGrids[projectName] = loaded.grid;\n newProjectFocused[projectName] = loaded.focusedPanelId;\n set({\n currentProject: projectName,\n panels: mergedPanels,\n grid: loaded.grid,\n focusedPanelId: loaded.focusedPanelId,\n projectGrids: newProjectGrids,\n projectFocused: newProjectFocused,\n });\n } else {\n // Create empty layout — EmptyPanel will show quick-open buttons\n const p = createPanel();\n const newGrid = [[p.id]];\n\n // Merge into flat panels map\n const mergedPanels = { ...panels, [p.id]: p };\n newProjectGrids[projectName] = newGrid;\n newProjectFocused[projectName] = p.id;\n savePanelLayout(projectName, { panels: { [p.id]: p }, grid: newGrid, focusedPanelId: p.id });\n set({\n currentProject: projectName,\n panels: mergedPanels,\n grid: newGrid,\n focusedPanelId: p.id,\n projectGrids: newProjectGrids,\n projectFocused: newProjectFocused,\n });\n }\n },\n\n reloadProject: (projectName) => {\n const { projectGrids, projectFocused, panels } = get();\n // Clear in-memory cache so switchProject re-reads from localStorage\n const newGrids = { ...projectGrids };\n const newFocused = { ...projectFocused };\n delete newGrids[projectName];\n delete newFocused[projectName];\n\n // Remove old panels belonging to this project from flat map\n const oldGrid = projectGrids[projectName];\n const oldPanelIds = oldGrid ? new Set(oldGrid.flat()) : new Set<string>();\n const cleanedPanels = { ...panels };\n for (const id of oldPanelIds) delete cleanedPanels[id];\n\n set({ projectGrids: newGrids, projectFocused: newFocused, panels: cleanedPanels, currentProject: null });\n // Re-trigger full load from localStorage\n get().switchProject(projectName);\n },\n\n setFocusedPanel: (panelId) => {\n if (get().panels[panelId]) set({ focusedPanelId: panelId });\n },\n\n openTab: (tabDef, panelId?) => {\n const mobile = get().isMobile();\n // On mobile, always open in first panel (tabs merged in mobile nav)\n const pid = mobile\n ? (get().grid[0]?.[0] ?? resolvePanel(panelId))\n : resolvePanel(panelId);\n const panel = get().panels[pid];\n if (!panel) return \"\";\n\n // Terminal: compute next available index if not provided\n if (tabDef.type === \"terminal\" && !tabDef.metadata?.terminalIndex) {\n const allTabs = Object.values(get().panels).flatMap((p) => p.tabs);\n const terminalNums = allTabs\n .filter((t) => t.type === \"terminal\")\n .map((t) => {\n const match = t.id.match(/^terminal:(\\d+)/);\n return match ? parseInt(match[1]!, 10) : 0;\n });\n const nextIndex = terminalNums.length > 0 ? Math.max(...terminalNums) + 1 : 1;\n tabDef = { ...tabDef, metadata: { ...tabDef.metadata, terminalIndex: nextIndex } };\n }\n\n const baseId = deriveTabId(tabDef.type, tabDef.metadata);\n\n // Singleton check — focus existing across ALL panels\n if (SINGLETON_TYPES.has(tabDef.type)) {\n for (const p of Object.values(get().panels)) {\n const existing = p.tabs.find((t) => t.id === baseId);\n if (existing) {\n set((s) => ({\n focusedPanelId: p.id,\n panels: {\n ...s.panels,\n [p.id]: {\n ...p,\n activeTabId: existing.id,\n tabHistory: pushHistory(p.tabHistory, existing.id),\n },\n },\n }));\n persist();\n return existing.id;\n }\n }\n }\n\n // Mobile: dedup across all panels (merged tab bar shows all tabs)\n if (mobile) {\n for (const gpid of get().grid.flat()) {\n const p = get().panels[gpid];\n if (!p) continue;\n const existing = p.tabs.find((t) => t.id === baseId || t.id.startsWith(`${baseId}@`));\n if (existing) {\n set((s) => ({\n focusedPanelId: p.id,\n panels: {\n ...s.panels,\n [p.id]: { ...p, activeTabId: existing.id, tabHistory: pushHistory(p.tabHistory, existing.id) },\n },\n }));\n persist();\n return existing.id;\n }\n }\n }\n\n // Non-singleton: dedup within SAME panel only\n const currentPanel = get().panels[pid]!;\n const existingInPanel = currentPanel.tabs.find((t) => t.id === baseId);\n if (existingInPanel) {\n set((s) => ({\n panels: {\n ...s.panels,\n [pid]: {\n ...currentPanel,\n activeTabId: existingInPanel.id,\n tabHistory: pushHistory(currentPanel.tabHistory, existingInPanel.id),\n },\n },\n }));\n persist();\n return existingInPanel.id;\n }\n\n // Check if same base ID exists in OTHER panels (split case)\n const existsElsewhere = Object.values(get().panels).some(\n (p) => p.id !== pid && p.tabs.some((t) => t.id === baseId),\n );\n const id = existsElsewhere ? `${baseId}@${pid}` : baseId;\n\n const tab: Tab = { ...tabDef, id };\n set((s) => {\n const p = s.panels[pid]!;\n return {\n focusedPanelId: pid,\n panels: {\n ...s.panels,\n [pid]: {\n ...p,\n tabs: [...p.tabs, tab],\n activeTabId: id,\n tabHistory: pushHistory(p.tabHistory, id),\n },\n },\n };\n });\n persist();\n return id;\n },\n\n closeTab: (tabId, panelId?) => {\n const panel = panelId ? get().panels[panelId] : findPanel(tabId);\n if (!panel) return;\n const pid = panel.id;\n\n set((s) => {\n const p = s.panels[pid]!;\n const newTabs = p.tabs.filter((t) => t.id !== tabId);\n const newHistory = p.tabHistory.filter((h) => h !== tabId);\n let newActive = p.activeTabId;\n if (p.activeTabId === tabId) {\n const prevId = newHistory.length > 0 ? newHistory[newHistory.length - 1] : null;\n newActive = prevId && newTabs.some((t) => t.id === prevId)\n ? prevId\n : newTabs[newTabs.length - 1]?.id ?? null;\n }\n\n // Auto-close panel if empty and not the last one in current grid\n const gridPanelCount = s.grid.flat().length;\n if (newTabs.length === 0 && gridPanelCount > 1) {\n const { [pid]: _, ...rest } = s.panels;\n const newGrid = gridRemovePanel(s.grid, pid);\n const newFocused = s.focusedPanelId === pid ? Object.keys(rest)[0]! : s.focusedPanelId;\n return { panels: rest, grid: newGrid, focusedPanelId: newFocused };\n }\n\n return {\n panels: { ...s.panels, [pid]: { ...p, tabs: newTabs, activeTabId: newActive, tabHistory: newHistory } },\n };\n });\n persist();\n },\n\n setActiveTab: (tabId, panelId?) => {\n const panel = panelId ? get().panels[panelId] : findPanel(tabId);\n if (!panel) return;\n const pid = panel.id;\n set((s) => {\n const p = s.panels[pid]!;\n return {\n focusedPanelId: pid,\n panels: { ...s.panels, [pid]: { ...p, activeTabId: tabId, tabHistory: pushHistory(p.tabHistory, tabId) } },\n };\n });\n persist();\n },\n\n updateTab: (tabId, updates) => {\n const panel = findPanel(tabId);\n if (!panel) return;\n set((s) => ({\n panels: {\n ...s.panels,\n [panel.id]: { ...panel, tabs: panel.tabs.map((t) => (t.id === tabId ? { ...t, ...updates } : t)) },\n },\n }));\n persist();\n },\n\n reorderTab: (tabId, panelId, newIndex) => {\n const panel = get().panels[panelId];\n if (!panel) return;\n const oldIndex = panel.tabs.findIndex((t) => t.id === tabId);\n if (oldIndex === -1 || oldIndex === newIndex) return;\n const newTabs = [...panel.tabs];\n const [moved] = newTabs.splice(oldIndex, 1);\n newTabs.splice(newIndex, 0, moved!);\n set((s) => ({ panels: { ...s.panels, [panelId]: { ...panel, tabs: newTabs } } }));\n persist();\n },\n\n moveTab: (tabId, fromPanelId, toPanelId, insertIndex?) => {\n if (fromPanelId === toPanelId) return;\n const from = get().panels[fromPanelId];\n const to = get().panels[toPanelId];\n if (!from || !to) return;\n\n const tab = from.tabs.find((t) => t.id === tabId);\n if (!tab) return;\n\n const fromTabs = from.tabs.filter((t) => t.id !== tabId);\n const fromHistory = from.tabHistory.filter((h) => h !== tabId);\n const fromActive = from.activeTabId === tabId\n ? (fromHistory[fromHistory.length - 1] ?? fromTabs[fromTabs.length - 1]?.id ?? null)\n : from.activeTabId;\n\n const toTabs = [...to.tabs];\n if (insertIndex !== undefined) toTabs.splice(insertIndex, 0, tab);\n else toTabs.push(tab);\n\n set((s) => {\n const gridPanelCount = s.grid.flat().length;\n // Auto-close empty source panel if not last in current grid\n if (fromTabs.length === 0 && gridPanelCount > 1) {\n const { [fromPanelId]: _, ...rest } = s.panels;\n return {\n panels: {\n ...rest,\n [toPanelId]: { ...to, tabs: toTabs, activeTabId: tabId, tabHistory: pushHistory(to.tabHistory, tabId) },\n },\n grid: gridRemovePanel(s.grid, fromPanelId),\n focusedPanelId: toPanelId,\n };\n }\n\n return {\n focusedPanelId: toPanelId,\n panels: {\n ...s.panels,\n [fromPanelId]: { ...from, tabs: fromTabs, activeTabId: fromActive, tabHistory: fromHistory },\n [toPanelId]: { ...to, tabs: toTabs, activeTabId: tabId, tabHistory: pushHistory(to.tabHistory, tabId) },\n },\n };\n });\n persist();\n },\n\n splitPanel: (direction, tabId, sourcePanelId, targetPanelId?) => {\n const { grid, panels } = get();\n const mobile = get().isMobile();\n const source = panels[sourcePanelId];\n if (!source) return false;\n\n const tab = source.tabs.find((t) => t.id === tabId);\n if (!tab) return false;\n\n // Use target panel's position for grid insertion (where the drop happened)\n const positionPanelId = targetPanelId ?? sourcePanelId;\n const pos = findPanelPosition(grid, positionPanelId);\n if (!pos) return false;\n\n // Check constraints — grid is row-major: grid[row][col]\n const isHorizontal = direction === \"left\" || direction === \"right\";\n const isVertical = direction === \"up\" || direction === \"down\";\n if (isHorizontal && (grid[pos.row]?.length ?? 0) >= maxColumns(mobile)) return false;\n if (isVertical && grid.length >= MAX_ROWS) return false;\n\n const newPanel = createPanel([tab], tab.id);\n newPanel.tabHistory = [tab.id];\n\n // Remove tab from source\n const srcTabs = source.tabs.filter((t) => t.id !== tabId);\n const srcHistory = source.tabHistory.filter((h) => h !== tabId);\n const srcActive = source.activeTabId === tabId\n ? (srcHistory[srcHistory.length - 1] ?? srcTabs[srcTabs.length - 1]?.id ?? null)\n : source.activeTabId;\n\n let newGrid: string[][];\n if (isHorizontal) {\n // Add column within the same row\n newGrid = grid.map((row, r) => {\n if (r !== pos.row) return row;\n const newRow = [...row];\n const insertCol = direction === \"right\" ? pos.col + 1 : pos.col;\n newRow.splice(insertCol, 0, newPanel.id);\n return newRow;\n });\n } else {\n // Add new row to the grid\n newGrid = [...grid];\n const insertRow = direction === \"down\" ? pos.row + 1 : pos.row;\n newGrid.splice(insertRow, 0, [newPanel.id]);\n }\n\n set((s) => {\n const gridPanelCount = s.grid.flat().length;\n let updatedPanels = {\n ...s.panels,\n [newPanel.id]: newPanel,\n };\n\n // If source is now empty and not last panel in grid, remove it\n if (srcTabs.length === 0 && gridPanelCount > 1) {\n const { [sourcePanelId]: _, ...rest } = updatedPanels;\n updatedPanels = rest;\n newGrid = gridRemovePanel(newGrid, sourcePanelId);\n } else {\n updatedPanels[sourcePanelId] = { ...source, tabs: srcTabs, activeTabId: srcActive, tabHistory: srcHistory };\n }\n\n return { panels: updatedPanels, grid: newGrid, focusedPanelId: newPanel.id };\n });\n persist();\n return true;\n },\n\n closePanel: (panelId) => {\n const { panels, grid } = get();\n if (grid.flat().length <= 1) return;\n\n const panel = panels[panelId];\n if (!panel) return;\n\n // Find neighbor to merge tabs into\n const pos = findPanelPosition(grid, panelId);\n const allIds = grid.flat();\n const idx = allIds.indexOf(panelId);\n const neighborId = idx > 0 ? allIds[idx - 1]! : allIds[1]!;\n const neighbor = panels[neighborId];\n if (!neighbor) return;\n\n set((s) => {\n const { [panelId]: _, ...rest } = s.panels;\n const mergedTabs = [...neighbor.tabs, ...panel.tabs];\n const mergedActive = neighbor.activeTabId ?? panel.activeTabId;\n return {\n panels: {\n ...rest,\n [neighborId]: { ...neighbor, tabs: mergedTabs, activeTabId: mergedActive, tabHistory: [...neighbor.tabHistory, ...panel.tabHistory] },\n },\n grid: gridRemovePanel(s.grid, panelId),\n focusedPanelId: neighborId,\n };\n });\n persist();\n },\n\n getPanelForTab: (tabId) => findPanel(tabId),\n\n isMobile: () => typeof window !== \"undefined\" && window.innerWidth < 768,\n };\n});\n","import { create } from \"zustand\";\nimport { usePanelStore } from \"./panel-store\";\nimport { getNextUntitledNumber } from \"./panel-utils\";\n\nexport type TabType =\n | \"terminal\"\n | \"chat\"\n | \"editor\"\n | \"database\"\n | \"sqlite\"\n | \"postgres\"\n | \"git-diff\"\n | \"settings\"\n | \"ports\"\n | \"extension\"\n | \"extension-webview\"\n | \"conflict-editor\";\n\nexport interface Tab {\n id: string;\n type: TabType;\n title: string;\n projectId: string | null;\n metadata?: Record<string, unknown>;\n closable: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Facade store — delegates to panel-store, exposes focused panel's tabs\n// ---------------------------------------------------------------------------\ninterface TabStore {\n /** Tabs of the focused panel */\n tabs: Tab[];\n /** Active tab in focused panel */\n activeTabId: string | null;\n tabHistory: string[];\n currentProject: string | null;\n switchProject: (projectName: string) => void;\n openTab: (tab: Omit<Tab, \"id\">) => string;\n closeTab: (id: string) => void;\n setActiveTab: (id: string) => void;\n updateTab: (id: string, updates: Partial<Omit<Tab, \"id\">>) => void;\n openNewFile: () => string;\n}\n\nexport const useTabStore = create<TabStore>()(() => ({\n tabs: [],\n activeTabId: null,\n tabHistory: [],\n currentProject: null,\n\n switchProject: (projectName: string) => {\n usePanelStore.getState().switchProject(projectName);\n syncFromPanelStore();\n },\n\n openTab: (tabDef) => {\n const id = usePanelStore.getState().openTab(tabDef);\n syncFromPanelStore();\n return id;\n },\n\n closeTab: (id) => {\n usePanelStore.getState().closeTab(id);\n syncFromPanelStore();\n },\n\n setActiveTab: (id) => {\n usePanelStore.getState().setActiveTab(id);\n syncFromPanelStore();\n },\n\n updateTab: (id, updates) => {\n usePanelStore.getState().updateTab(id, updates);\n syncFromPanelStore();\n },\n\n openNewFile: () => {\n const ps = usePanelStore.getState();\n const num = getNextUntitledNumber(ps.panels);\n const id = ps.openTab({\n type: \"editor\",\n title: `Untitled-${num}`,\n projectId: null,\n metadata: { isUntitled: true, untitledNumber: num },\n closable: true,\n });\n syncFromPanelStore();\n return id;\n },\n}));\n\n// ---------------------------------------------------------------------------\n// Sync focused panel state → tab-store for backward compat\n// ---------------------------------------------------------------------------\nfunction syncFromPanelStore() {\n const ps = usePanelStore.getState();\n const focused = ps.panels[ps.focusedPanelId];\n useTabStore.setState({\n tabs: focused?.tabs ?? [],\n activeTabId: focused?.activeTabId ?? null,\n tabHistory: focused?.tabHistory ?? [],\n currentProject: ps.currentProject,\n });\n}\n\n// Subscribe to panel-store changes to keep tab-store in sync\nusePanelStore.subscribe(() => syncFromPanelStore());\n"],"mappings":"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"}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./createLucideIcon-BjHrJDVb.js";var t=e(`table`,[[`path`,{d:`M12 3v18`,key:`108xh3`}],[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M3 9h18`,key:`1pudct`}],[`path`,{d:`M3 15h18`,key:`5xshup`}]]);export{t};
|
|
1
|
+
import{t as e}from"./createLucideIcon-BjHrJDVb.js";var t=e(`table`,[[`path`,{d:`M12 3v18`,key:`108xh3`}],[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M3 9h18`,key:`1pudct`}],[`path`,{d:`M3 15h18`,key:`5xshup`}]]);export{t};
|
|
2
|
+
//# sourceMappingURL=table-BzjWcs87.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table-BzjWcs87.js","names":[],"sources":["../../../node_modules/.bun/lucide-react@0.577.0+b1ab299f0a400331/node_modules/lucide-react/dist/esm/icons/table.js"],"sourcesContent":["/**\n * @license lucide-react v0.577.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 3v18\", key: \"108xh3\" }],\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M3 9h18\", key: \"1pudct\" }],\n [\"path\", { d: \"M3 15h18\", key: \"5xshup\" }]\n];\nconst Table = createLucideIcon(\"table\", __iconNode);\n\nexport { __iconNode, Table as default };\n//# sourceMappingURL=table.js.map\n"],"x_google_ignoreList":[0],"mappings":"mDAeA,IAAM,EAAQ,EAAiB,QANZ,CACjB,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,SAAU,CAAC,CAC1C,CAAC,OAAQ,CAAE,MAAO,KAAM,OAAQ,KAAM,EAAG,IAAK,EAAG,IAAK,GAAI,IAAK,IAAK,SAAU,CAAC,CAC/E,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,SAAU,CAAC,CACzC,CAAC,OAAQ,CAAE,EAAG,WAAY,IAAK,SAAU,CAAC,CAC3C,CACkD"}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{b as t,x as n}from"./vendor-markdown-0Mxgxy0L.js";import"./api-client-DIhJ5qVW.js";import{n as r}from"./settings-store-CVrIYYCB.js";import"./vendor-mermaid-Cl50p6TB.js";import{n as i}from"./utils-CQux7CsO.js";import{H as a,et as o,tt as s}from"./index-DJtqbPFT.js";import{n as c,r as l,t as u}from"./vendor-xterm-K3_Xwigj.js";var d=e(n(),1),f={background:`#0f1419`,foreground:`#e5e7eb`,cursor:`#e5e7eb`,selectionBackground:`#3b82f640`,black:`#1a1f2e`,red:`#ef4444`,green:`#10b981`,yellow:`#f59e0b`,blue:`#3b82f6`,magenta:`#a855f7`,cyan:`#06b6d4`,white:`#e5e7eb`,brightBlack:`#6b7280`,brightRed:`#f87171`,brightGreen:`#34d399`,brightYellow:`#fbbf24`,brightBlue:`#60a5fa`,brightMagenta:`#c084fc`,brightCyan:`#22d3ee`,brightWhite:`#f9fafb`},p={background:`#ffffff`,foreground:`#1a1f2e`,cursor:`#1a1f2e`,selectionBackground:`#2563eb30`,black:`#1a1f2e`,red:`#dc2626`,green:`#059669`,yellow:`#d97706`,blue:`#2563eb`,magenta:`#9333ea`,cyan:`#0891b2`,white:`#f8fafc`,brightBlack:`#64748b`,brightRed:`#ef4444`,brightGreen:`#10b981`,brightYellow:`#f59e0b`,brightBlue:`#3b82f6`,brightMagenta:`#a855f7`,brightCyan:`#06b6d4`,brightWhite:`#ffffff`};function m(e){return e===`system`?window.matchMedia(`(prefers-color-scheme: dark)`).matches?f:p:e===`light`?p:f}var h=`RESIZE:`;function g(e){let{sessionId:t,containerRef:n}=e,i=(0,d.useRef)(null),a=(0,d.useRef)(null),o=(0,d.useRef)(null),s=(0,d.useRef)(null),f=(0,d.useRef)(0),[p,g]=(0,d.useState)(!1),[_,v]=(0,d.useState)(!1),[y,b]=(0,d.useState)(!1),x=(0,d.useRef)(t),S=(0,d.useCallback)(e=>{let t=o.current;t?.readyState===WebSocket.OPEN&&t.send(e)},[]),C=(0,d.useCallback)(()=>i.current?.getSelection()??``,[]),w=(0,d.useCallback)(()=>{let e=i.current,t=o.current;e&&t?.readyState===WebSocket.OPEN&&t.send(`${h}${e.cols},${e.rows}`)},[]),T=(0,d.useCallback)(()=>{s.current&&clearTimeout(s.current),o.current?.close(),o.current=null,x.current=`new`,f.current=0,b(!1),g(!1),v(!1),setTimeout(()=>E(),0)},[]),E=(0,d.useCallback)(()=>{let t=i.current;if(!t)return;let n=window.location.protocol===`https:`?`wss:`:`ws:`,r=e.projectName??``,a=x.current,s=`${n}//${window.location.host}/ws/project/${encodeURIComponent(r)}/terminal/${a}`,c=new WebSocket(s);o.current=c,c.onopen=()=>{g(!0),v(!1),f.current=0,w()},c.onmessage=e=>{if(typeof e.data==`string`){if(e.data.startsWith(`{`))try{let n=JSON.parse(e.data);if(n.type===`session`||n.type===`error`||n.type===`exited`||n.type===`ping`){n.type===`session`&&n.id&&(x.current=n.id),n.type===`error`&&t.write(`\r\n\x1b[31mError: ${n.message}\x1b[0m\r\n`),n.type===`exited`&&b(!0);return}}catch{}t.write(e.data)}},c.onclose=()=>{g(!1),D()},c.onerror=()=>{c.close()}},[t,w]);function D(){let e=Math.min(1e3*2**f.current,3e4);f.current++,v(!0),s.current=setTimeout(()=>{E()},e)}return(0,d.useEffect)(()=>{let e=n.current;if(!e)return;let t=new l({cursorBlink:!0,fontSize:13,fontFamily:`var(--font-mono)`,theme:m(r.getState().theme)}),d=new c,f=new u;t.loadAddon(d),t.loadAddon(f),t.open(e),d.fit(),i.current=t,a.current=d,t.onData(e=>{let t=o.current;t?.readyState===WebSocket.OPEN&&t.send(e)}),E();let p=new ResizeObserver(()=>{try{d.fit(),w()}catch{}});p.observe(e);let h=r.getState().theme,g=r.subscribe(e=>{e.theme!==h&&(h=e.theme,t.options.theme=m(e.theme))});return()=>{g(),p.disconnect(),s.current&&clearTimeout(s.current),o.current?.close(),o.current=null,t.dispose(),i.current=null,a.current=null}},[t]),{connected:p,reconnecting:_,exited:y,sendData:S,getSelection:C,restart:T}}var _=t(),v=[{label:`Tab`,value:` `},{label:`Esc`,value:`\x1B`},{label:`Ctrl`,value:null,isModifier:!0},{label:`↑`,value:`\x1B[A`},{label:`↓`,value:`\x1B[B`},{label:`←`,value:`\x1B[D`},{label:`→`,value:`\x1B[C`}],y=(0,d.memo)(function({metadata:e}){let t=e?.sessionId??`new`,n=e?.projectName,r=(0,d.useRef)(null),{connected:c,reconnecting:l,exited:u,sendData:f,getSelection:p,restart:m}=g({sessionId:t,projectName:n,containerRef:r}),[h,y]=(0,d.useState)(!1),[b,x]=(0,d.useState)(null);(0,d.useEffect)(()=>{let e=window.visualViewport;if(!e)return;function t(){e&&x(e.height)}return e.addEventListener(`resize`,t),()=>e.removeEventListener(`resize`,t)},[]);let S=(0,d.useCallback)(()=>{(r.current?.querySelector(`.xterm-helper-textarea`))?.focus()},[]),C=(0,d.useCallback)(e=>{if(S(),h&&e.length===1){let t=e.toLowerCase().charCodeAt(0)-96;t>=1&&t<=26&&f(String.fromCharCode(t)),y(!1);return}f(e)},[h,f,S]),w=(0,d.useCallback)(async()=>{let e=p();e&&await navigator.clipboard.writeText(e)},[p]),T=(0,d.useCallback)(async()=>{try{let e=await navigator.clipboard.readText();e&&(f(e),S())}catch{}},[f,S]),E=typeof window<`u`&&`ontouchstart`in window;return(0,_.jsxs)(`div`,{className:`flex flex-col h-full`,style:b?{maxHeight:`${b}px`}:void 0,children:[(0,_.jsxs)(`div`,{className:`flex items-center gap-2 px-3 py-1 bg-surface border-b border-border text-xs`,children:[(0,_.jsx)(`span`,{className:i(`size-2 rounded-full`,u?`bg-error`:c?`bg-success`:l?`bg-warning`:`bg-error`)}),(0,_.jsx)(`span`,{className:`text-text-secondary`,children:u?`Process exited`:c?`Connected`:l?`Reconnecting...`:`Disconnected`}),u&&(0,_.jsxs)(`button`,{onClick:m,className:`flex items-center gap-1 px-1.5 py-0.5 rounded text-xs bg-surface-elevated text-text-primary hover:bg-primary hover:text-primary-foreground active:bg-primary active:text-primary-foreground transition-colors`,children:[(0,_.jsx)(a,{size:10}),`Restart`]}),(0,_.jsx)(`span`,{className:`text-text-subtle ml-auto font-mono`,children:t})]}),(0,_.jsx)(`div`,{ref:r,className:`flex-1 min-h-0 bg-background p-1`}),E&&(0,_.jsxs)(`div`,{className:`flex items-center gap-1 px-2 py-1.5 bg-surface border-t border-border overflow-x-auto`,children:[(0,_.jsx)(`button`,{onClick:w,className:`px-2 py-1.5 rounded text-xs min-w-[36px] min-h-[32px] bg-surface-elevated text-text-primary active:bg-primary active:text-primary-foreground transition-colors select-none`,children:(0,_.jsx)(o,{size:14})}),(0,_.jsx)(`button`,{onClick:T,className:`px-2 py-1.5 rounded text-xs min-w-[36px] min-h-[32px] bg-surface-elevated text-text-primary active:bg-primary active:text-primary-foreground transition-colors select-none`,children:(0,_.jsx)(s,{size:14})}),(0,_.jsx)(`div`,{className:`w-px h-5 bg-border mx-0.5`}),v.map(e=>(0,_.jsx)(`button`,{onClick:()=>{e.label===`Ctrl`?y(!h):e.value&&C(e.value)},className:i(`px-3 py-1.5 rounded text-xs font-mono min-w-[36px] min-h-[32px]`,`bg-surface-elevated text-text-primary active:bg-primary active:text-primary-foreground`,`transition-colors select-none`,e.label===`Ctrl`&&h&&`bg-primary text-primary-foreground`),children:e.label},e.label))]})]})});export{y as TerminalTab};
|
|
1
|
+
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{b as t,x as n}from"./vendor-markdown-0Mxgxy0L.js";import"./api-client-DIhJ5qVW.js";import{n as r}from"./settings-store-CVrIYYCB.js";import"./vendor-mermaid-Cl50p6TB.js";import{n as i}from"./utils-CQux7CsO.js";import{H as a,et as o,tt as s}from"./index-DJtqbPFT.js";import{n as c,r as l,t as u}from"./vendor-xterm-K3_Xwigj.js";var d=e(n(),1),f={background:`#0f1419`,foreground:`#e5e7eb`,cursor:`#e5e7eb`,selectionBackground:`#3b82f640`,black:`#1a1f2e`,red:`#ef4444`,green:`#10b981`,yellow:`#f59e0b`,blue:`#3b82f6`,magenta:`#a855f7`,cyan:`#06b6d4`,white:`#e5e7eb`,brightBlack:`#6b7280`,brightRed:`#f87171`,brightGreen:`#34d399`,brightYellow:`#fbbf24`,brightBlue:`#60a5fa`,brightMagenta:`#c084fc`,brightCyan:`#22d3ee`,brightWhite:`#f9fafb`},p={background:`#ffffff`,foreground:`#1a1f2e`,cursor:`#1a1f2e`,selectionBackground:`#2563eb30`,black:`#1a1f2e`,red:`#dc2626`,green:`#059669`,yellow:`#d97706`,blue:`#2563eb`,magenta:`#9333ea`,cyan:`#0891b2`,white:`#f8fafc`,brightBlack:`#64748b`,brightRed:`#ef4444`,brightGreen:`#10b981`,brightYellow:`#f59e0b`,brightBlue:`#3b82f6`,brightMagenta:`#a855f7`,brightCyan:`#06b6d4`,brightWhite:`#ffffff`};function m(e){return e===`system`?window.matchMedia(`(prefers-color-scheme: dark)`).matches?f:p:e===`light`?p:f}var h=`RESIZE:`;function g(e){let{sessionId:t,containerRef:n}=e,i=(0,d.useRef)(null),a=(0,d.useRef)(null),o=(0,d.useRef)(null),s=(0,d.useRef)(null),f=(0,d.useRef)(0),[p,g]=(0,d.useState)(!1),[_,v]=(0,d.useState)(!1),[y,b]=(0,d.useState)(!1),x=(0,d.useRef)(t),S=(0,d.useCallback)(e=>{let t=o.current;t?.readyState===WebSocket.OPEN&&t.send(e)},[]),C=(0,d.useCallback)(()=>i.current?.getSelection()??``,[]),w=(0,d.useCallback)(()=>{let e=i.current,t=o.current;e&&t?.readyState===WebSocket.OPEN&&t.send(`${h}${e.cols},${e.rows}`)},[]),T=(0,d.useCallback)(()=>{s.current&&clearTimeout(s.current),o.current?.close(),o.current=null,x.current=`new`,f.current=0,b(!1),g(!1),v(!1),setTimeout(()=>E(),0)},[]),E=(0,d.useCallback)(()=>{let t=i.current;if(!t)return;let n=window.location.protocol===`https:`?`wss:`:`ws:`,r=e.projectName??``,a=x.current,s=`${n}//${window.location.host}/ws/project/${encodeURIComponent(r)}/terminal/${a}`,c=new WebSocket(s);o.current=c,c.onopen=()=>{g(!0),v(!1),f.current=0,w()},c.onmessage=e=>{if(typeof e.data==`string`){if(e.data.startsWith(`{`))try{let n=JSON.parse(e.data);if(n.type===`session`||n.type===`error`||n.type===`exited`||n.type===`ping`){n.type===`session`&&n.id&&(x.current=n.id),n.type===`error`&&t.write(`\r\n\x1b[31mError: ${n.message}\x1b[0m\r\n`),n.type===`exited`&&b(!0);return}}catch{}t.write(e.data)}},c.onclose=()=>{g(!1),D()},c.onerror=()=>{c.close()}},[t,w]);function D(){let e=Math.min(1e3*2**f.current,3e4);f.current++,v(!0),s.current=setTimeout(()=>{E()},e)}return(0,d.useEffect)(()=>{let e=n.current;if(!e)return;let t=new l({cursorBlink:!0,fontSize:13,fontFamily:`var(--font-mono)`,theme:m(r.getState().theme)}),d=new c,f=new u;t.loadAddon(d),t.loadAddon(f),t.open(e),d.fit(),i.current=t,a.current=d,t.onData(e=>{let t=o.current;t?.readyState===WebSocket.OPEN&&t.send(e)}),E();let p=new ResizeObserver(()=>{try{d.fit(),w()}catch{}});p.observe(e);let h=r.getState().theme,g=r.subscribe(e=>{e.theme!==h&&(h=e.theme,t.options.theme=m(e.theme))});return()=>{g(),p.disconnect(),s.current&&clearTimeout(s.current),o.current?.close(),o.current=null,t.dispose(),i.current=null,a.current=null}},[t]),{connected:p,reconnecting:_,exited:y,sendData:S,getSelection:C,restart:T}}var _=t(),v=[{label:`Tab`,value:` `},{label:`Esc`,value:`\x1B`},{label:`Ctrl`,value:null,isModifier:!0},{label:`↑`,value:`\x1B[A`},{label:`↓`,value:`\x1B[B`},{label:`←`,value:`\x1B[D`},{label:`→`,value:`\x1B[C`}],y=(0,d.memo)(function({metadata:e}){let t=e?.sessionId??`new`,n=e?.projectName,r=(0,d.useRef)(null),{connected:c,reconnecting:l,exited:u,sendData:f,getSelection:p,restart:m}=g({sessionId:t,projectName:n,containerRef:r}),[h,y]=(0,d.useState)(!1),[b,x]=(0,d.useState)(null);(0,d.useEffect)(()=>{let e=window.visualViewport;if(!e)return;function t(){e&&x(e.height)}return e.addEventListener(`resize`,t),()=>e.removeEventListener(`resize`,t)},[]);let S=(0,d.useCallback)(()=>{(r.current?.querySelector(`.xterm-helper-textarea`))?.focus()},[]),C=(0,d.useCallback)(e=>{if(S(),h&&e.length===1){let t=e.toLowerCase().charCodeAt(0)-96;t>=1&&t<=26&&f(String.fromCharCode(t)),y(!1);return}f(e)},[h,f,S]),w=(0,d.useCallback)(async()=>{let e=p();e&&await navigator.clipboard.writeText(e)},[p]),T=(0,d.useCallback)(async()=>{try{let e=await navigator.clipboard.readText();e&&(f(e),S())}catch{}},[f,S]),E=typeof window<`u`&&`ontouchstart`in window;return(0,_.jsxs)(`div`,{className:`flex flex-col h-full`,style:b?{maxHeight:`${b}px`}:void 0,children:[(0,_.jsxs)(`div`,{className:`flex items-center gap-2 px-3 py-1 bg-surface border-b border-border text-xs`,children:[(0,_.jsx)(`span`,{className:i(`size-2 rounded-full`,u?`bg-error`:c?`bg-success`:l?`bg-warning`:`bg-error`)}),(0,_.jsx)(`span`,{className:`text-text-secondary`,children:u?`Process exited`:c?`Connected`:l?`Reconnecting...`:`Disconnected`}),u&&(0,_.jsxs)(`button`,{onClick:m,className:`flex items-center gap-1 px-1.5 py-0.5 rounded text-xs bg-surface-elevated text-text-primary hover:bg-primary hover:text-primary-foreground active:bg-primary active:text-primary-foreground transition-colors`,children:[(0,_.jsx)(a,{size:10}),`Restart`]}),(0,_.jsx)(`span`,{className:`text-text-subtle ml-auto font-mono`,children:t})]}),(0,_.jsx)(`div`,{ref:r,className:`flex-1 min-h-0 bg-background p-1`}),E&&(0,_.jsxs)(`div`,{className:`flex items-center gap-1 px-2 py-1.5 bg-surface border-t border-border overflow-x-auto`,children:[(0,_.jsx)(`button`,{onClick:w,className:`px-2 py-1.5 rounded text-xs min-w-[36px] min-h-[32px] bg-surface-elevated text-text-primary active:bg-primary active:text-primary-foreground transition-colors select-none`,children:(0,_.jsx)(o,{size:14})}),(0,_.jsx)(`button`,{onClick:T,className:`px-2 py-1.5 rounded text-xs min-w-[36px] min-h-[32px] bg-surface-elevated text-text-primary active:bg-primary active:text-primary-foreground transition-colors select-none`,children:(0,_.jsx)(s,{size:14})}),(0,_.jsx)(`div`,{className:`w-px h-5 bg-border mx-0.5`}),v.map(e=>(0,_.jsx)(`button`,{onClick:()=>{e.label===`Ctrl`?y(!h):e.value&&C(e.value)},className:i(`px-3 py-1.5 rounded text-xs font-mono min-w-[36px] min-h-[32px]`,`bg-surface-elevated text-text-primary active:bg-primary active:text-primary-foreground`,`transition-colors select-none`,e.label===`Ctrl`&&h&&`bg-primary text-primary-foreground`),children:e.label},e.label))]})]})});export{y as TerminalTab};
|
|
2
|
+
//# sourceMappingURL=terminal-tab-XKe1TZiV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal-tab-XKe1TZiV.js","names":[],"sources":["../../../src/web/hooks/use-terminal.ts","../../../src/web/components/terminal/terminal-tab.tsx"],"sourcesContent":["import { useEffect, useRef, useCallback, useState } from \"react\";\nimport { Terminal, type ITheme } from \"@xterm/xterm\";\nimport { FitAddon } from \"@xterm/addon-fit\";\nimport { WebLinksAddon } from \"@xterm/addon-web-links\";\nimport { useSettingsStore, type Theme } from \"@/stores/settings-store\";\n\nconst DARK_THEME: ITheme = {\n background: \"#0f1419\",\n foreground: \"#e5e7eb\",\n cursor: \"#e5e7eb\",\n selectionBackground: \"#3b82f640\",\n black: \"#1a1f2e\",\n red: \"#ef4444\",\n green: \"#10b981\",\n yellow: \"#f59e0b\",\n blue: \"#3b82f6\",\n magenta: \"#a855f7\",\n cyan: \"#06b6d4\",\n white: \"#e5e7eb\",\n brightBlack: \"#6b7280\",\n brightRed: \"#f87171\",\n brightGreen: \"#34d399\",\n brightYellow: \"#fbbf24\",\n brightBlue: \"#60a5fa\",\n brightMagenta: \"#c084fc\",\n brightCyan: \"#22d3ee\",\n brightWhite: \"#f9fafb\",\n};\n\nconst LIGHT_THEME: ITheme = {\n background: \"#ffffff\",\n foreground: \"#1a1f2e\",\n cursor: \"#1a1f2e\",\n selectionBackground: \"#2563eb30\",\n black: \"#1a1f2e\",\n red: \"#dc2626\",\n green: \"#059669\",\n yellow: \"#d97706\",\n blue: \"#2563eb\",\n magenta: \"#9333ea\",\n cyan: \"#0891b2\",\n white: \"#f8fafc\",\n brightBlack: \"#64748b\",\n brightRed: \"#ef4444\",\n brightGreen: \"#10b981\",\n brightYellow: \"#f59e0b\",\n brightBlue: \"#3b82f6\",\n brightMagenta: \"#a855f7\",\n brightCyan: \"#06b6d4\",\n brightWhite: \"#ffffff\",\n};\n\nfunction resolveTheme(theme: Theme): ITheme {\n if (theme === \"system\") {\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? DARK_THEME : LIGHT_THEME;\n }\n return theme === \"light\" ? LIGHT_THEME : DARK_THEME;\n}\n\ninterface UseTerminalOptions {\n sessionId: string;\n projectName?: string;\n containerRef: React.RefObject<HTMLDivElement | null>;\n}\n\ninterface UseTerminalReturn {\n connected: boolean;\n reconnecting: boolean;\n exited: boolean;\n sendData: (data: string) => void;\n getSelection: () => string;\n restart: () => void;\n}\n\nconst RESIZE_PREFIX = \"\\x01RESIZE:\";\n\nexport function useTerminal(\n options: UseTerminalOptions,\n): UseTerminalReturn {\n const { sessionId, containerRef } = options;\n const termRef = useRef<Terminal | null>(null);\n const fitRef = useRef<FitAddon | null>(null);\n const wsRef = useRef<WebSocket | null>(null);\n const reconnectTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const reconnectAttempts = useRef(0);\n const [connected, setConnected] = useState(false);\n const [reconnecting, setReconnecting] = useState(false);\n const [exited, setExited] = useState(false);\n const actualSessionId = useRef(sessionId); // Track server-assigned session ID\n\n const sendData = useCallback((data: string) => {\n const ws = wsRef.current;\n if (ws?.readyState === WebSocket.OPEN) {\n ws.send(data);\n }\n }, []);\n\n const getSelection = useCallback(() => {\n return termRef.current?.getSelection() ?? \"\";\n }, []);\n\n const sendResize = useCallback(() => {\n const term = termRef.current;\n const ws = wsRef.current;\n if (term && ws?.readyState === WebSocket.OPEN) {\n ws.send(`${RESIZE_PREFIX}${term.cols},${term.rows}`);\n }\n }, []);\n\n const restart = useCallback(() => {\n // Close existing WS, reset to \"new\" session, reconnect\n if (reconnectTimer.current) clearTimeout(reconnectTimer.current);\n wsRef.current?.close();\n wsRef.current = null;\n actualSessionId.current = \"new\";\n reconnectAttempts.current = 0;\n setExited(false);\n setConnected(false);\n setReconnecting(false);\n // connectWs will be called after this via setTimeout to allow state to settle\n setTimeout(() => connectWs(), 0);\n }, []); // eslint-disable-line react-hooks/exhaustive-deps\n\n const connectWs = useCallback(() => {\n const term = termRef.current;\n if (!term) return;\n\n const protocol = window.location.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n const projectName = options.projectName ?? \"\";\n // Use actual session ID from server on reconnect (not \"new\")\n const sid = actualSessionId.current;\n const url = `${protocol}//${window.location.host}/ws/project/${encodeURIComponent(projectName)}/terminal/${sid}`;\n\n const ws = new WebSocket(url);\n wsRef.current = ws;\n\n ws.onopen = () => {\n setConnected(true);\n setReconnecting(false);\n reconnectAttempts.current = 0;\n sendResize();\n };\n\n ws.onmessage = (event) => {\n if (typeof event.data === \"string\") {\n // Filter JSON control messages from terminal output\n if (event.data.startsWith(\"{\")) {\n try {\n const msg = JSON.parse(event.data);\n if (msg.type === \"session\" || msg.type === \"error\" || msg.type === \"exited\" || msg.type === \"ping\") {\n if (msg.type === \"session\" && msg.id) {\n actualSessionId.current = msg.id; // Save for reconnect\n }\n if (msg.type === \"error\") {\n term.write(`\\r\\n\\x1b[31mError: ${msg.message}\\x1b[0m\\r\\n`);\n }\n if (msg.type === \"exited\") {\n setExited(true);\n }\n return; // Don't write raw JSON to terminal\n }\n } catch {\n // Not JSON, write as terminal output\n }\n }\n term.write(event.data);\n }\n };\n\n ws.onclose = () => {\n setConnected(false);\n scheduleReconnect();\n };\n\n ws.onerror = () => {\n ws.close();\n };\n }, [sessionId, sendResize]); // eslint-disable-line react-hooks/exhaustive-deps\n\n function scheduleReconnect() {\n const delay = Math.min(\n 1000 * Math.pow(2, reconnectAttempts.current),\n 30000,\n );\n reconnectAttempts.current++;\n setReconnecting(true);\n reconnectTimer.current = setTimeout(() => {\n connectWs();\n }, delay);\n }\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n const term = new Terminal({\n cursorBlink: true,\n fontSize: 13,\n fontFamily: \"var(--font-mono)\",\n theme: resolveTheme(useSettingsStore.getState().theme),\n });\n\n const fitAddon = new FitAddon();\n const webLinksAddon = new WebLinksAddon();\n\n term.loadAddon(fitAddon);\n term.loadAddon(webLinksAddon);\n term.open(container);\n fitAddon.fit();\n\n termRef.current = term;\n fitRef.current = fitAddon;\n\n // Wire input to WS\n term.onData((data) => {\n const ws = wsRef.current;\n if (ws?.readyState === WebSocket.OPEN) {\n ws.send(data);\n }\n });\n\n // Connect WS\n connectWs();\n\n // ResizeObserver for auto-fit\n const resizeObserver = new ResizeObserver(() => {\n try {\n fitAddon.fit();\n sendResize();\n } catch {\n // Ignore fit errors during teardown\n }\n });\n resizeObserver.observe(container);\n\n // React to theme changes\n let prevTheme = useSettingsStore.getState().theme;\n const unsubTheme = useSettingsStore.subscribe((state) => {\n if (state.theme !== prevTheme) {\n prevTheme = state.theme;\n term.options.theme = resolveTheme(state.theme);\n }\n });\n\n return () => {\n unsubTheme();\n resizeObserver.disconnect();\n if (reconnectTimer.current) clearTimeout(reconnectTimer.current);\n wsRef.current?.close();\n wsRef.current = null;\n term.dispose();\n termRef.current = null;\n fitRef.current = null;\n };\n }, [sessionId]); // eslint-disable-line react-hooks/exhaustive-deps\n\n return { connected, reconnecting, exited, sendData, getSelection, restart };\n}\n","import { useRef, useEffect, useState, useCallback, memo } from \"react\";\nimport { useTerminal } from \"@/hooks/use-terminal\";\nimport { cn } from \"@/lib/utils\";\nimport { Copy, ClipboardPaste, RotateCcw } from \"lucide-react\";\nimport \"@xterm/xterm/css/xterm.css\";\n\ninterface TerminalTabProps {\n metadata?: Record<string, unknown>;\n}\n\nconst MOBILE_KEYS = [\n { label: \"Tab\", value: \"\\t\" },\n { label: \"Esc\", value: \"\\x1b\" },\n { label: \"Ctrl\", value: null, isModifier: true },\n { label: \"\\u2191\", value: \"\\x1b[A\" },\n { label: \"\\u2193\", value: \"\\x1b[B\" },\n { label: \"\\u2190\", value: \"\\x1b[D\" },\n { label: \"\\u2192\", value: \"\\x1b[C\" },\n] as const;\n\nexport const TerminalTab = memo(function TerminalTab({ metadata }: TerminalTabProps) {\n const sessionId = (metadata?.sessionId as string) ?? \"new\";\n const projectName = metadata?.projectName as string | undefined;\n const containerRef = useRef<HTMLDivElement>(null);\n const { connected, reconnecting, exited, sendData, getSelection, restart } = useTerminal({ sessionId, projectName, containerRef });\n const [ctrlMode, setCtrlMode] = useState(false);\n const [viewportHeight, setViewportHeight] = useState<number | null>(null);\n\n // Adjust height when mobile keyboard opens\n useEffect(() => {\n const vv = window.visualViewport;\n if (!vv) return;\n\n function handleResize() {\n if (!vv) return;\n setViewportHeight(vv.height);\n }\n\n vv.addEventListener(\"resize\", handleResize);\n return () => vv.removeEventListener(\"resize\", handleResize);\n }, []);\n\n const focusTerminal = useCallback(() => {\n const termElement = containerRef.current?.querySelector(\n \".xterm-helper-textarea\",\n ) as HTMLTextAreaElement | null;\n termElement?.focus();\n }, []);\n\n const sendKey = useCallback(\n (value: string) => {\n focusTerminal();\n\n if (ctrlMode && value.length === 1) {\n // Ctrl+key: send char code 1-26 for a-z\n const code = value.toLowerCase().charCodeAt(0) - 96;\n if (code >= 1 && code <= 26) {\n sendData(String.fromCharCode(code));\n }\n setCtrlMode(false);\n return;\n }\n\n sendData(value);\n },\n [ctrlMode, sendData, focusTerminal],\n );\n\n const handleCopy = useCallback(async () => {\n const selection = getSelection();\n if (selection) {\n await navigator.clipboard.writeText(selection);\n }\n }, [getSelection]);\n\n const handlePaste = useCallback(async () => {\n try {\n const text = await navigator.clipboard.readText();\n if (text) {\n sendData(text);\n focusTerminal();\n }\n } catch {\n // Clipboard permission denied\n }\n }, [sendData, focusTerminal]);\n\n const isMobile = typeof window !== \"undefined\" && \"ontouchstart\" in window;\n\n return (\n <div\n className=\"flex flex-col h-full\"\n style={viewportHeight ? { maxHeight: `${viewportHeight}px` } : undefined}\n >\n {/* Status bar */}\n <div className=\"flex items-center gap-2 px-3 py-1 bg-surface border-b border-border text-xs\">\n <span\n className={cn(\n \"size-2 rounded-full\",\n exited ? \"bg-error\" : connected ? \"bg-success\" : reconnecting ? \"bg-warning\" : \"bg-error\",\n )}\n />\n <span className=\"text-text-secondary\">\n {exited\n ? \"Process exited\"\n : connected\n ? \"Connected\"\n : reconnecting\n ? \"Reconnecting...\"\n : \"Disconnected\"}\n </span>\n {exited && (\n <button\n onClick={restart}\n className=\"flex items-center gap-1 px-1.5 py-0.5 rounded text-xs bg-surface-elevated text-text-primary hover:bg-primary hover:text-primary-foreground active:bg-primary active:text-primary-foreground transition-colors\"\n >\n <RotateCcw size={10} />\n Restart\n </button>\n )}\n <span className=\"text-text-subtle ml-auto font-mono\">{sessionId}</span>\n </div>\n\n {/* Terminal container */}\n <div ref={containerRef} className=\"flex-1 min-h-0 bg-background p-1\" />\n\n {/* Mobile toolbar */}\n {isMobile && (\n <div className=\"flex items-center gap-1 px-2 py-1.5 bg-surface border-t border-border overflow-x-auto\">\n <button\n onClick={handleCopy}\n className=\"px-2 py-1.5 rounded text-xs min-w-[36px] min-h-[32px] bg-surface-elevated text-text-primary active:bg-primary active:text-primary-foreground transition-colors select-none\"\n >\n <Copy size={14} />\n </button>\n <button\n onClick={handlePaste}\n className=\"px-2 py-1.5 rounded text-xs min-w-[36px] min-h-[32px] bg-surface-elevated text-text-primary active:bg-primary active:text-primary-foreground transition-colors select-none\"\n >\n <ClipboardPaste size={14} />\n </button>\n <div className=\"w-px h-5 bg-border mx-0.5\" />\n {MOBILE_KEYS.map((key) => (\n <button\n key={key.label}\n onClick={() => {\n if (key.label === \"Ctrl\") {\n setCtrlMode(!ctrlMode);\n } else if (key.value) {\n sendKey(key.value);\n }\n }}\n className={cn(\n \"px-3 py-1.5 rounded text-xs font-mono min-w-[36px] min-h-[32px]\",\n \"bg-surface-elevated text-text-primary active:bg-primary active:text-primary-foreground\",\n \"transition-colors select-none\",\n key.label === \"Ctrl\" && ctrlMode && \"bg-primary text-primary-foreground\",\n )}\n >\n {key.label}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n});\n"],"mappings":"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"}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import{t as e}from"./createLucideIcon-BjHrJDVb.js";var t=e(`text-wrap`,[[`path`,{d:`m16 16-3 3 3 3`,key:`117b85`}],[`path`,{d:`M3 12h14.5a1 1 0 0 1 0 7H13`,key:`18xa6z`}],[`path`,{d:`M3 19h6`,key:`1ygdsz`}],[`path`,{d:`M3 5h18`,key:`1u36vt`}]]);export{t};
|
|
1
|
+
import{t as e}from"./createLucideIcon-BjHrJDVb.js";var t=e(`text-wrap`,[[`path`,{d:`m16 16-3 3 3 3`,key:`117b85`}],[`path`,{d:`M3 12h14.5a1 1 0 0 1 0 7H13`,key:`18xa6z`}],[`path`,{d:`M3 19h6`,key:`1ygdsz`}],[`path`,{d:`M3 5h18`,key:`1u36vt`}]]);export{t};
|
|
2
|
+
//# sourceMappingURL=text-wrap-DJz9Bgpa.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-wrap-DJz9Bgpa.js","names":[],"sources":["../../../node_modules/.bun/lucide-react@0.577.0+b1ab299f0a400331/node_modules/lucide-react/dist/esm/icons/text-wrap.js"],"sourcesContent":["/**\n * @license lucide-react v0.577.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"m16 16-3 3 3 3\", key: \"117b85\" }],\n [\"path\", { d: \"M3 12h14.5a1 1 0 0 1 0 7H13\", key: \"18xa6z\" }],\n [\"path\", { d: \"M3 19h6\", key: \"1ygdsz\" }],\n [\"path\", { d: \"M3 5h18\", key: \"1u36vt\" }]\n];\nconst TextWrap = createLucideIcon(\"text-wrap\", __iconNode);\n\nexport { __iconNode, TextWrap as default };\n//# sourceMappingURL=text-wrap.js.map\n"],"x_google_ignoreList":[0],"mappings":"mDAeA,IAAM,EAAW,EAAiB,YANf,CACjB,CAAC,OAAQ,CAAE,EAAG,iBAAkB,IAAK,SAAU,CAAC,CAChD,CAAC,OAAQ,CAAE,EAAG,8BAA+B,IAAK,SAAU,CAAC,CAC7D,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,SAAU,CAAC,CACzC,CAAC,OAAQ,CAAE,EAAG,UAAW,IAAK,SAAU,CAAC,CAC1C,CACyD"}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{x as t}from"./vendor-markdown-0Mxgxy0L.js";import{i as n,r}from"./api-client-DIhJ5qVW.js";var i=e(t(),1);function a(e,t,a){let[o,s]=(0,i.useState)(null),[c,l]=(0,i.useState)(!1);return(0,i.useEffect)(()=>{let i,o=/^(\/|[A-Za-z]:[/\\])/.test(e)?`/api/fs/raw?path=${encodeURIComponent(e)}`:`${n(t)}/files/raw?path=${encodeURIComponent(e)}`,c=r();return fetch(o,{headers:c?{Authorization:`Bearer ${c}`}:{}}).then(e=>{if(!e.ok)throw Error(`Failed`);return e.blob()}).then(e=>{let t=a?new Blob([e],{type:a}):e,n=URL.createObjectURL(t);i=n,s(n)}).catch(()=>l(!0)),()=>{i&&URL.revokeObjectURL(i)}},[e,t,a]),{blobUrl:o,error:c}}export{a as t};
|
|
1
|
+
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{x as t}from"./vendor-markdown-0Mxgxy0L.js";import{i as n,r}from"./api-client-DIhJ5qVW.js";var i=e(t(),1);function a(e,t,a){let[o,s]=(0,i.useState)(null),[c,l]=(0,i.useState)(!1);return(0,i.useEffect)(()=>{let i,o=/^(\/|[A-Za-z]:[/\\])/.test(e)?`/api/fs/raw?path=${encodeURIComponent(e)}`:`${n(t)}/files/raw?path=${encodeURIComponent(e)}`,c=r();return fetch(o,{headers:c?{Authorization:`Bearer ${c}`}:{}}).then(e=>{if(!e.ok)throw Error(`Failed`);return e.blob()}).then(e=>{let t=a?new Blob([e],{type:a}):e,n=URL.createObjectURL(t);i=n,s(n)}).catch(()=>l(!0)),()=>{i&&URL.revokeObjectURL(i)}},[e,t,a]),{blobUrl:o,error:c}}export{a as t};
|
|
2
|
+
//# sourceMappingURL=use-blob-url-QX-XajU8.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-blob-url-QX-XajU8.js","names":[],"sources":["../../../src/web/components/editor/use-blob-url.ts"],"sourcesContent":["import { useEffect, useState } from \"react\";\nimport { projectUrl, getAuthToken } from \"@/lib/api-client\";\n\n/** Shared hook: fetch a project file as a blob URL via /files/raw endpoint.\n * Detects absolute paths (external files) and uses /api/fs/raw instead. */\nexport function useBlobUrl(\n filePath: string,\n projectName: string,\n mimeOverride?: string,\n) {\n const [blobUrl, setBlobUrl] = useState<string | null>(null);\n const [error, setError] = useState(false);\n\n useEffect(() => {\n let revoke: string | undefined;\n const isExternal = /^(\\/|[A-Za-z]:[/\\\\])/.test(filePath);\n const url = isExternal\n ? `/api/fs/raw?path=${encodeURIComponent(filePath)}`\n : `${projectUrl(projectName)}/files/raw?path=${encodeURIComponent(filePath)}`;\n const token = getAuthToken();\n fetch(url, { headers: token ? { Authorization: `Bearer ${token}` } : {} })\n .then((r) => {\n if (!r.ok) throw new Error(\"Failed\");\n return r.blob();\n })\n .then((blob) => {\n const final = mimeOverride ? new Blob([blob], { type: mimeOverride }) : blob;\n const u = URL.createObjectURL(final);\n revoke = u;\n setBlobUrl(u);\n })\n .catch(() => setError(true));\n return () => {\n if (revoke) URL.revokeObjectURL(revoke);\n };\n }, [filePath, projectName, mimeOverride]);\n\n return { blobUrl, error };\n}\n"],"mappings":"mKAKA,SAAgB,EACd,EACA,EACA,EACA,CACA,GAAM,CAAC,EAAS,IAAA,EAAA,EAAA,UAAsC,KAAK,CACrD,CAAC,EAAO,IAAA,EAAA,EAAA,UAAqB,GAAM,CA0BzC,OAxBA,EAAA,EAAA,eAAgB,CACd,IAAI,EAEE,EADa,uBAAuB,KAAK,EAAS,CAEpD,oBAAoB,mBAAmB,EAAS,GAChD,GAAG,EAAW,EAAY,CAAC,kBAAkB,mBAAmB,EAAS,GACvE,EAAQ,GAAc,CAa5B,OAZA,MAAM,EAAK,CAAE,QAAS,EAAQ,CAAE,cAAe,UAAU,IAAS,CAAG,EAAE,CAAE,CAAC,CACvE,KAAM,GAAM,CACX,GAAI,CAAC,EAAE,GAAI,MAAU,MAAM,SAAS,CACpC,OAAO,EAAE,MAAM,EACf,CACD,KAAM,GAAS,CACd,IAAM,EAAQ,EAAe,IAAI,KAAK,CAAC,EAAK,CAAE,CAAE,KAAM,EAAc,CAAC,CAAG,EAClE,EAAI,IAAI,gBAAgB,EAAM,CACpC,EAAS,EACT,EAAW,EAAE,EACb,CACD,UAAY,EAAS,GAAK,CAAC,KACjB,CACP,GAAQ,IAAI,gBAAgB,EAAO,GAExC,CAAC,EAAU,EAAa,EAAa,CAAC,CAElC,CAAE,UAAS,QAAO"}
|
|
@@ -8,4 +8,5 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
|
|
|
8
8
|
monaco.config({ paths: { vs: '...' } })
|
|
9
9
|
|
|
10
10
|
For more please check the link https://github.com/suren-atoyan/monaco-loader#config
|
|
11
|
-
`},L=ne(oe)(I),se={config:ie},ce=function(){var e=[...arguments];return function(t){return e.reduceRight(function(e,t){return t(e)},t)}};function R(e,t){return Object.keys(t).forEach(function(n){t[n]instanceof Object&&e[n]&&Object.assign(t[n],R(e[n],t[n]))}),l(l({},e),t)}var le={type:`cancelation`,msg:`operation is manually canceled`};function z(e){var t=!1,n=new Promise(function(n,r){e.then(function(e){return t?r(le):n(e)}),e.catch(r)});return n.cancel=function(){return t=!0},n}var ue=[`monaco`],B=f(F.create({config:te,isInitialized:!1,resolve:null,reject:null,monaco:null}),2),V=B[0],H=B[1];function de(e){var t=se.config(e),n=t.monaco,r=u(t,ue);H(function(e){return{config:R(e.config,r),monaco:n}})}function fe(){var e=V(function(e){return{monaco:e.monaco,isInitialized:e.isInitialized,resolve:e.resolve}});if(!e.isInitialized){if(H({isInitialized:!0}),e.monaco)return e.resolve(e.monaco),z(W);if(window.monaco&&window.monaco.editor)return U(window.monaco),e.resolve(window.monaco),z(W);ce(pe,he)(ge)}return z(W)}function pe(e){return document.body.appendChild(e)}function me(e){var t=document.createElement(`script`);return e&&(t.src=e),t}function he(e){var t=V(function(e){return{config:e.config,reject:e.reject}}),n=me(`${t.config.paths.vs}/loader.js`);return n.onload=function(){return e()},n.onerror=t.reject,n}function ge(){var e=V(function(e){return{config:e.config,resolve:e.resolve,reject:e.reject}}),t=window.require;t.config(e.config),t([`vs/editor/editor.main`],function(t){var n=t.m||t;U(n),e.resolve(n)},function(t){e.reject(t)})}function U(e){V().monaco||H({monaco:e})}function _e(){return V(function(e){return e.monaco})}var W=new Promise(function(e,t){return H({resolve:e,reject:t})}),G={config:de,init:fe,__getMonacoInstance:_e},K=e(t(),1),q={wrapper:{display:`flex`,position:`relative`,textAlign:`initial`},fullWidth:{width:`100%`},hide:{display:`none`}},ve={container:{display:`flex`,height:`100%`,width:`100%`,justifyContent:`center`,alignItems:`center`}};function ye({children:e}){return K.createElement(`div`,{style:ve.container},e)}var be=ye;function xe({width:e,height:t,isEditorReady:n,loading:r,_ref:i,className:a,wrapperProps:o}){return K.createElement(`section`,{style:{...q.wrapper,width:e,height:t},...o},!n&&K.createElement(be,null,r),K.createElement(`div`,{ref:i,style:{...q.fullWidth,...!n&&q.hide},className:a}))}var J=(0,K.memo)(xe);function Se(e){(0,K.useEffect)(e,[])}var Y=Se;function Ce(e,t,n=!0){let r=(0,K.useRef)(!0);(0,K.useEffect)(r.current||!n?()=>{r.current=!1}:e,t)}var X=Ce;function Z(){}function Q(e,t,n,r){return we(e,r)||Te(e,t,n,r)}function we(e,t){return e.editor.getModel(Ee(e,t))}function Te(e,t,n,r){return e.editor.createModel(t,n,r?Ee(e,r):void 0)}function Ee(e,t){return e.Uri.parse(t)}function De({original:e,modified:t,language:n,originalLanguage:r,modifiedLanguage:i,originalModelPath:a,modifiedModelPath:o,keepCurrentOriginalModel:s=!1,keepCurrentModifiedModel:c=!1,theme:l=`light`,loading:u=`Loading...`,options:d={},height:f=`100%`,width:p=`100%`,className:m,wrapperProps:h={},beforeMount:g=Z,onMount:_=Z}){let[v,y]=(0,K.useState)(!1),[b,x]=(0,K.useState)(!0),S=(0,K.useRef)(null),C=(0,K.useRef)(null),w=(0,K.useRef)(null),T=(0,K.useRef)(_),E=(0,K.useRef)(g),D=(0,K.useRef)(!1);Y(()=>{let e=G.init();return e.then(e=>(C.current=e)&&x(!1)).catch(e=>e?.type!==`cancelation`&&console.error(`Monaco initialization: error:`,e)),()=>S.current?A():e.cancel()}),X(()=>{if(S.current&&C.current){let t=S.current.getOriginalEditor(),i=Q(C.current,e||``,r||n||`text`,a||``);i!==t.getModel()&&t.setModel(i)}},[a],v),X(()=>{if(S.current&&C.current){let e=S.current.getModifiedEditor(),r=Q(C.current,t||``,i||n||`text`,o||``);r!==e.getModel()&&e.setModel(r)}},[o],v),X(()=>{let e=S.current.getModifiedEditor();e.getOption(C.current.editor.EditorOption.readOnly)?e.setValue(t||``):t!==e.getValue()&&(e.executeEdits(``,[{range:e.getModel().getFullModelRange(),text:t||``,forceMoveMarkers:!0}]),e.pushUndoStop())},[t],v),X(()=>{S.current?.getModel()?.original.setValue(e||``)},[e],v),X(()=>{let{original:e,modified:t}=S.current.getModel();C.current.editor.setModelLanguage(e,r||n||`text`),C.current.editor.setModelLanguage(t,i||n||`text`)},[n,r,i],v),X(()=>{C.current?.editor.setTheme(l)},[l],v),X(()=>{S.current?.updateOptions(d)},[d],v);let O=(0,K.useCallback)(()=>{if(!C.current)return;E.current(C.current);let s=Q(C.current,e||``,r||n||`text`,a||``),c=Q(C.current,t||``,i||n||`text`,o||``);S.current?.setModel({original:s,modified:c})},[n,t,i,e,r,a,o]),k=(0,K.useCallback)(()=>{!D.current&&w.current&&(S.current=C.current.editor.createDiffEditor(w.current,{automaticLayout:!0,...d}),O(),C.current?.editor.setTheme(l),y(!0),D.current=!0)},[d,l,O]);(0,K.useEffect)(()=>{v&&T.current(S.current,C.current)},[v]),(0,K.useEffect)(()=>{!b&&!v&&k()},[b,v,k]);function A(){let e=S.current?.getModel();s||e?.original?.dispose(),c||e?.modified?.dispose(),S.current?.dispose()}return K.createElement(J,{width:p,height:f,isEditorReady:v,loading:u,_ref:w,className:m,wrapperProps:h})}var Oe=(0,K.memo)(De);function ke(e){let t=(0,K.useRef)();return(0,K.useEffect)(()=>{t.current=e},[e]),t.current}var Ae=ke,$=new Map;function je({defaultValue:e,defaultLanguage:t,defaultPath:n,value:r,language:i,path:a,theme:o=`light`,line:s,loading:c=`Loading...`,options:l={},overrideServices:u={},saveViewState:d=!0,keepCurrentModel:f=!1,width:p=`100%`,height:m=`100%`,className:h,wrapperProps:g={},beforeMount:_=Z,onMount:v=Z,onChange:y,onValidate:b=Z}){let[x,S]=(0,K.useState)(!1),[C,w]=(0,K.useState)(!0),T=(0,K.useRef)(null),E=(0,K.useRef)(null),D=(0,K.useRef)(null),O=(0,K.useRef)(v),k=(0,K.useRef)(_),A=(0,K.useRef)(),j=(0,K.useRef)(r),ee=Ae(a),M=(0,K.useRef)(!1),N=(0,K.useRef)(!1);Y(()=>{let e=G.init();return e.then(e=>(T.current=e)&&w(!1)).catch(e=>e?.type!==`cancelation`&&console.error(`Monaco initialization: error:`,e)),()=>E.current?F():e.cancel()}),X(()=>{let o=Q(T.current,e||r||``,t||i||``,a||n||``);o!==E.current?.getModel()&&(d&&$.set(ee,E.current?.saveViewState()),E.current?.setModel(o),d&&E.current?.restoreViewState($.get(a)))},[a],x),X(()=>{E.current?.updateOptions(l)},[l],x),X(()=>{!E.current||r===void 0||(E.current.getOption(T.current.editor.EditorOption.readOnly)?E.current.setValue(r):r!==E.current.getValue()&&(N.current=!0,E.current.executeEdits(``,[{range:E.current.getModel().getFullModelRange(),text:r,forceMoveMarkers:!0}]),E.current.pushUndoStop(),N.current=!1))},[r],x),X(()=>{let e=E.current?.getModel();e&&i&&T.current?.editor.setModelLanguage(e,i)},[i],x),X(()=>{s!==void 0&&E.current?.revealLine(s)},[s],x),X(()=>{T.current?.editor.setTheme(o)},[o],x);let P=(0,K.useCallback)(()=>{if(!(!D.current||!T.current)&&!M.current){k.current(T.current);let c=a||n,f=Q(T.current,r||e||``,t||i||``,c||``);E.current=T.current?.editor.create(D.current,{model:f,automaticLayout:!0,...l},u),d&&E.current.restoreViewState($.get(c)),T.current.editor.setTheme(o),s!==void 0&&E.current.revealLine(s),S(!0),M.current=!0}},[e,t,n,r,i,a,l,u,d,o,s]);(0,K.useEffect)(()=>{x&&O.current(E.current,T.current)},[x]),(0,K.useEffect)(()=>{!C&&!x&&P()},[C,x,P]),j.current=r,(0,K.useEffect)(()=>{x&&y&&(A.current?.dispose(),A.current=E.current?.onDidChangeModelContent(e=>{N.current||y(E.current.getValue(),e)}))},[x,y]),(0,K.useEffect)(()=>{if(x){let e=T.current.editor.onDidChangeMarkers(e=>{let t=E.current.getModel()?.uri;if(t&&e.find(e=>e.path===t.path)){let e=T.current.editor.getModelMarkers({resource:t});b?.(e)}});return()=>{e?.dispose()}}return()=>{}},[x,b]);function F(){A.current?.dispose(),f?d&&$.set(a,E.current.saveViewState()):E.current.getModel()?.dispose(),E.current.dispose()}return K.createElement(J,{width:p,height:m,isEditorReady:x,loading:c,_ref:D,className:h,wrapperProps:g})}var Me=(0,K.memo)(je);function Ne(){let e=n(e=>e.theme),t=()=>e===`dark`?`vs-dark`:e===`light`?`light`:window.matchMedia(`(prefers-color-scheme: dark)`).matches?`vs-dark`:`light`,[r,i]=(0,K.useState)(t);return(0,K.useEffect)(()=>{if(i(t()),e===`system`){let e=window.matchMedia(`(prefers-color-scheme: dark)`),t=()=>i(e.matches?`vs-dark`:`light`);return e.addEventListener(`change`,t),()=>e.removeEventListener(`change`,t)}},[e]),r}export{Me as n,Oe as r,Ne as t};
|
|
11
|
+
`},L=ne(oe)(I),se={config:ie},ce=function(){var e=[...arguments];return function(t){return e.reduceRight(function(e,t){return t(e)},t)}};function R(e,t){return Object.keys(t).forEach(function(n){t[n]instanceof Object&&e[n]&&Object.assign(t[n],R(e[n],t[n]))}),l(l({},e),t)}var le={type:`cancelation`,msg:`operation is manually canceled`};function z(e){var t=!1,n=new Promise(function(n,r){e.then(function(e){return t?r(le):n(e)}),e.catch(r)});return n.cancel=function(){return t=!0},n}var ue=[`monaco`],B=f(F.create({config:te,isInitialized:!1,resolve:null,reject:null,monaco:null}),2),V=B[0],H=B[1];function de(e){var t=se.config(e),n=t.monaco,r=u(t,ue);H(function(e){return{config:R(e.config,r),monaco:n}})}function fe(){var e=V(function(e){return{monaco:e.monaco,isInitialized:e.isInitialized,resolve:e.resolve}});if(!e.isInitialized){if(H({isInitialized:!0}),e.monaco)return e.resolve(e.monaco),z(W);if(window.monaco&&window.monaco.editor)return U(window.monaco),e.resolve(window.monaco),z(W);ce(pe,he)(ge)}return z(W)}function pe(e){return document.body.appendChild(e)}function me(e){var t=document.createElement(`script`);return e&&(t.src=e),t}function he(e){var t=V(function(e){return{config:e.config,reject:e.reject}}),n=me(`${t.config.paths.vs}/loader.js`);return n.onload=function(){return e()},n.onerror=t.reject,n}function ge(){var e=V(function(e){return{config:e.config,resolve:e.resolve,reject:e.reject}}),t=window.require;t.config(e.config),t([`vs/editor/editor.main`],function(t){var n=t.m||t;U(n),e.resolve(n)},function(t){e.reject(t)})}function U(e){V().monaco||H({monaco:e})}function _e(){return V(function(e){return e.monaco})}var W=new Promise(function(e,t){return H({resolve:e,reject:t})}),G={config:de,init:fe,__getMonacoInstance:_e},K=e(t(),1),q={wrapper:{display:`flex`,position:`relative`,textAlign:`initial`},fullWidth:{width:`100%`},hide:{display:`none`}},ve={container:{display:`flex`,height:`100%`,width:`100%`,justifyContent:`center`,alignItems:`center`}};function ye({children:e}){return K.createElement(`div`,{style:ve.container},e)}var be=ye;function xe({width:e,height:t,isEditorReady:n,loading:r,_ref:i,className:a,wrapperProps:o}){return K.createElement(`section`,{style:{...q.wrapper,width:e,height:t},...o},!n&&K.createElement(be,null,r),K.createElement(`div`,{ref:i,style:{...q.fullWidth,...!n&&q.hide},className:a}))}var J=(0,K.memo)(xe);function Se(e){(0,K.useEffect)(e,[])}var Y=Se;function Ce(e,t,n=!0){let r=(0,K.useRef)(!0);(0,K.useEffect)(r.current||!n?()=>{r.current=!1}:e,t)}var X=Ce;function Z(){}function Q(e,t,n,r){return we(e,r)||Te(e,t,n,r)}function we(e,t){return e.editor.getModel(Ee(e,t))}function Te(e,t,n,r){return e.editor.createModel(t,n,r?Ee(e,r):void 0)}function Ee(e,t){return e.Uri.parse(t)}function De({original:e,modified:t,language:n,originalLanguage:r,modifiedLanguage:i,originalModelPath:a,modifiedModelPath:o,keepCurrentOriginalModel:s=!1,keepCurrentModifiedModel:c=!1,theme:l=`light`,loading:u=`Loading...`,options:d={},height:f=`100%`,width:p=`100%`,className:m,wrapperProps:h={},beforeMount:g=Z,onMount:_=Z}){let[v,y]=(0,K.useState)(!1),[b,x]=(0,K.useState)(!0),S=(0,K.useRef)(null),C=(0,K.useRef)(null),w=(0,K.useRef)(null),T=(0,K.useRef)(_),E=(0,K.useRef)(g),D=(0,K.useRef)(!1);Y(()=>{let e=G.init();return e.then(e=>(C.current=e)&&x(!1)).catch(e=>e?.type!==`cancelation`&&console.error(`Monaco initialization: error:`,e)),()=>S.current?A():e.cancel()}),X(()=>{if(S.current&&C.current){let t=S.current.getOriginalEditor(),i=Q(C.current,e||``,r||n||`text`,a||``);i!==t.getModel()&&t.setModel(i)}},[a],v),X(()=>{if(S.current&&C.current){let e=S.current.getModifiedEditor(),r=Q(C.current,t||``,i||n||`text`,o||``);r!==e.getModel()&&e.setModel(r)}},[o],v),X(()=>{let e=S.current.getModifiedEditor();e.getOption(C.current.editor.EditorOption.readOnly)?e.setValue(t||``):t!==e.getValue()&&(e.executeEdits(``,[{range:e.getModel().getFullModelRange(),text:t||``,forceMoveMarkers:!0}]),e.pushUndoStop())},[t],v),X(()=>{S.current?.getModel()?.original.setValue(e||``)},[e],v),X(()=>{let{original:e,modified:t}=S.current.getModel();C.current.editor.setModelLanguage(e,r||n||`text`),C.current.editor.setModelLanguage(t,i||n||`text`)},[n,r,i],v),X(()=>{C.current?.editor.setTheme(l)},[l],v),X(()=>{S.current?.updateOptions(d)},[d],v);let O=(0,K.useCallback)(()=>{if(!C.current)return;E.current(C.current);let s=Q(C.current,e||``,r||n||`text`,a||``),c=Q(C.current,t||``,i||n||`text`,o||``);S.current?.setModel({original:s,modified:c})},[n,t,i,e,r,a,o]),k=(0,K.useCallback)(()=>{!D.current&&w.current&&(S.current=C.current.editor.createDiffEditor(w.current,{automaticLayout:!0,...d}),O(),C.current?.editor.setTheme(l),y(!0),D.current=!0)},[d,l,O]);(0,K.useEffect)(()=>{v&&T.current(S.current,C.current)},[v]),(0,K.useEffect)(()=>{!b&&!v&&k()},[b,v,k]);function A(){let e=S.current?.getModel();s||e?.original?.dispose(),c||e?.modified?.dispose(),S.current?.dispose()}return K.createElement(J,{width:p,height:f,isEditorReady:v,loading:u,_ref:w,className:m,wrapperProps:h})}var Oe=(0,K.memo)(De);function ke(e){let t=(0,K.useRef)();return(0,K.useEffect)(()=>{t.current=e},[e]),t.current}var Ae=ke,$=new Map;function je({defaultValue:e,defaultLanguage:t,defaultPath:n,value:r,language:i,path:a,theme:o=`light`,line:s,loading:c=`Loading...`,options:l={},overrideServices:u={},saveViewState:d=!0,keepCurrentModel:f=!1,width:p=`100%`,height:m=`100%`,className:h,wrapperProps:g={},beforeMount:_=Z,onMount:v=Z,onChange:y,onValidate:b=Z}){let[x,S]=(0,K.useState)(!1),[C,w]=(0,K.useState)(!0),T=(0,K.useRef)(null),E=(0,K.useRef)(null),D=(0,K.useRef)(null),O=(0,K.useRef)(v),k=(0,K.useRef)(_),A=(0,K.useRef)(),j=(0,K.useRef)(r),ee=Ae(a),M=(0,K.useRef)(!1),N=(0,K.useRef)(!1);Y(()=>{let e=G.init();return e.then(e=>(T.current=e)&&w(!1)).catch(e=>e?.type!==`cancelation`&&console.error(`Monaco initialization: error:`,e)),()=>E.current?F():e.cancel()}),X(()=>{let o=Q(T.current,e||r||``,t||i||``,a||n||``);o!==E.current?.getModel()&&(d&&$.set(ee,E.current?.saveViewState()),E.current?.setModel(o),d&&E.current?.restoreViewState($.get(a)))},[a],x),X(()=>{E.current?.updateOptions(l)},[l],x),X(()=>{!E.current||r===void 0||(E.current.getOption(T.current.editor.EditorOption.readOnly)?E.current.setValue(r):r!==E.current.getValue()&&(N.current=!0,E.current.executeEdits(``,[{range:E.current.getModel().getFullModelRange(),text:r,forceMoveMarkers:!0}]),E.current.pushUndoStop(),N.current=!1))},[r],x),X(()=>{let e=E.current?.getModel();e&&i&&T.current?.editor.setModelLanguage(e,i)},[i],x),X(()=>{s!==void 0&&E.current?.revealLine(s)},[s],x),X(()=>{T.current?.editor.setTheme(o)},[o],x);let P=(0,K.useCallback)(()=>{if(!(!D.current||!T.current)&&!M.current){k.current(T.current);let c=a||n,f=Q(T.current,r||e||``,t||i||``,c||``);E.current=T.current?.editor.create(D.current,{model:f,automaticLayout:!0,...l},u),d&&E.current.restoreViewState($.get(c)),T.current.editor.setTheme(o),s!==void 0&&E.current.revealLine(s),S(!0),M.current=!0}},[e,t,n,r,i,a,l,u,d,o,s]);(0,K.useEffect)(()=>{x&&O.current(E.current,T.current)},[x]),(0,K.useEffect)(()=>{!C&&!x&&P()},[C,x,P]),j.current=r,(0,K.useEffect)(()=>{x&&y&&(A.current?.dispose(),A.current=E.current?.onDidChangeModelContent(e=>{N.current||y(E.current.getValue(),e)}))},[x,y]),(0,K.useEffect)(()=>{if(x){let e=T.current.editor.onDidChangeMarkers(e=>{let t=E.current.getModel()?.uri;if(t&&e.find(e=>e.path===t.path)){let e=T.current.editor.getModelMarkers({resource:t});b?.(e)}});return()=>{e?.dispose()}}return()=>{}},[x,b]);function F(){A.current?.dispose(),f?d&&$.set(a,E.current.saveViewState()):E.current.getModel()?.dispose(),E.current.dispose()}return K.createElement(J,{width:p,height:m,isEditorReady:x,loading:c,_ref:D,className:h,wrapperProps:g})}var Me=(0,K.memo)(je);function Ne(){let e=n(e=>e.theme),t=()=>e===`dark`?`vs-dark`:e===`light`?`light`:window.matchMedia(`(prefers-color-scheme: dark)`).matches?`vs-dark`:`light`,[r,i]=(0,K.useState)(t);return(0,K.useEffect)(()=>{if(i(t()),e===`system`){let e=window.matchMedia(`(prefers-color-scheme: dark)`),t=()=>i(e.matches?`vs-dark`:`light`);return e.addEventListener(`change`,t),()=>e.removeEventListener(`change`,t)}},[e]),r}export{Me as n,Oe as r,Ne as t};
|
|
12
|
+
//# sourceMappingURL=use-monaco-theme-BePWbY58.js.map
|