@hienlh/ppm 0.13.8 → 0.13.10
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 +6 -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-ysK_Eixc.js +1 -0
- package/dist/web/assets/architecture-PBZL5I3N-By4Nv3Gj.js +1 -0
- package/dist/web/assets/{audio-preview-DQbX8gfL.js → audio-preview-DISP-2AE.js} +1 -1
- package/dist/web/assets/{chat-tab-BJQT9kie.js → chat-tab-lp_mVSG-.js} +8 -8
- package/dist/web/assets/code-editor-BofKrbM8.js +8 -0
- package/dist/web/assets/{conflict-editor-BKwJLX0D.js → conflict-editor-kaAZUFD5.js} +1 -1
- package/dist/web/assets/csv-parser-Dly5nqE1.js +6 -0
- package/dist/web/assets/{csv-preview-D5lmgVEy.js → csv-preview-7TsYBQI6.js} +3 -3
- package/dist/web/assets/data-grid-overlay-editor-BjjuE4-G.js +1 -0
- package/dist/web/assets/data-grid-types-BTQHYBUh.js +1 -0
- package/dist/web/assets/database-DOWH9-Vv.js +1 -0
- package/dist/web/assets/database-viewer-P38Vxzkx.js +1 -0
- package/dist/web/assets/{diff-viewer-SAtaBwNI.js → diff-viewer-DlJfbgNJ.js} +1 -1
- package/dist/web/assets/dist-0kPgRaVx.js +1 -0
- package/dist/web/assets/{esm-nXReYVnB.js → esm-zjerHxpO.js} +1 -1
- package/dist/web/assets/{extension-webview-PiV4bKJ1.js → extension-webview-5s2MUx38.js} +1 -1
- package/dist/web/assets/gitGraph-HDMCJU4V-BLXEKVf1.js +1 -0
- package/dist/web/assets/glide-data-grid-D5D1N3L7.js +136 -0
- package/dist/web/assets/glide-data-grid-nthEL3fk.css +1 -0
- package/dist/web/assets/{image-preview-CbFFD9BS.js → image-preview-C9osjEPa.js} +1 -1
- package/dist/web/assets/index-COOnLKGB.css +2 -0
- package/dist/web/assets/index-CpcqiQOx.js +27 -0
- package/dist/web/assets/info-3K5VOQVL-CEkPcChg.js +1 -0
- package/dist/web/assets/{input-BMvRUOr7.js → input-ozrR2DAV.js} +1 -1
- package/dist/web/assets/keybindings-store-COxqSoML.js +1 -0
- package/dist/web/assets/{markdown-renderer-CHWA0KAo.js → markdown-renderer-k3EA9XmF.js} +3 -3
- package/dist/web/assets/number-overlay-editor-BoRxunFN.js +9 -0
- package/dist/web/assets/packet-RMMSAZCW-DECxYTOi.js +1 -0
- package/dist/web/assets/{pdf-preview-DQMdjqa2.js → pdf-preview-DvgyxJX7.js} +1 -1
- package/dist/web/assets/pie-UPGHQEXC-cjpNfVG5.js +1 -0
- package/dist/web/assets/{port-forwarding-tab-9BpNC9_7.js → port-forwarding-tab-CUkU6wac.js} +1 -1
- package/dist/web/assets/{postgres-viewer-Bm5T51n6.js → postgres-viewer-C1w0tqQw.js} +3 -3
- package/dist/web/assets/radar-KQ55EAFF-Dnpi068b.js +1 -0
- package/dist/web/assets/{settings-store-BHBb62gq.js → settings-store-B-OmHo3J.js} +1 -1
- package/dist/web/assets/settings-tab-D0zKyVwg.js +1 -0
- package/dist/web/assets/sql-query-editor-46hLU7MI.js +3 -0
- package/dist/web/assets/sqlite-viewer-DrLi8P6y.js +1 -0
- package/dist/web/assets/terminal-tab-DqA3fEoQ.js +1 -0
- package/dist/web/assets/treemap-KZPCXAKY-DRyb1eiw.js +1 -0
- package/dist/web/assets/{use-monaco-theme-CP-vyTF8.js → use-monaco-theme-DgzxiZS5.js} +1 -1
- package/dist/web/assets/{vendor-mermaid-CMiurk2b.js → vendor-mermaid-CCmA_6Y0.js} +3 -3
- package/dist/web/assets/{video-preview-BLI_RruT.js → video-preview-BU7tibc4.js} +1 -1
- package/dist/web/assets/x-CG-_0yIW.js +1 -0
- package/dist/web/index.html +13 -14
- package/dist/web/sw.js +1 -1
- package/package.json +2 -1
- package/src/web/components/database/data-grid.tsx +18 -2
- package/src/web/components/database/database-viewer.tsx +19 -8
- package/src/web/components/database/export-button.tsx +38 -18
- package/src/web/components/database/glide-column-search.tsx +81 -0
- package/src/web/components/database/glide-context-menu.tsx +95 -0
- package/src/web/components/database/glide-data-grid.tsx +207 -0
- package/src/web/components/database/glide-data-preview-panel.tsx +113 -0
- package/src/web/components/database/glide-grid-pagination.tsx +34 -0
- package/src/web/components/database/glide-grid-theme.ts +82 -0
- package/src/web/components/database/glide-grid-toolbar.tsx +105 -0
- package/src/web/components/database/glide-grid-types.ts +81 -0
- package/src/web/components/database/glide-header-menu.tsx +111 -0
- package/src/web/components/database/glide-save-bar.tsx +33 -0
- package/src/web/components/database/sql-query-editor.tsx +14 -4
- package/src/web/components/database/use-database.ts +10 -2
- package/src/web/components/database/use-glide-cell-content.ts +159 -0
- package/src/web/components/database/use-glide-columns.ts +69 -0
- package/src/web/components/database/use-glide-grid-actions.ts +164 -0
- package/src/web/components/database/use-glide-pending-edits.ts +72 -0
- package/src/web/components/database/use-glide-row-pinning.ts +35 -0
- package/src/web/components/database/use-glide-selection.ts +48 -0
- package/src/web/components/editor/code-editor.tsx +126 -7
- package/src/web/components/layout/editor-panel.tsx +2 -2
- package/src/web/components/sqlite/sqlite-viewer.tsx +21 -12
- package/src/web/components/sqlite/use-sqlite.ts +1 -1
- package/src/web/hooks/use-terminal.ts +1 -1
- package/src/web/index.html +1 -0
- package/test.sql +1 -0
- package/dist/web/assets/ai-settings-section-CHgpQ_OP.js +0 -1
- package/dist/web/assets/architecture-PBZL5I3N-WMbLpD5Y.js +0 -1
- package/dist/web/assets/code-editor-CeKTvfyz.js +0 -8
- package/dist/web/assets/csv-parser-DO0dz4x_.js +0 -6
- package/dist/web/assets/database-DCT0OjgQ.js +0 -1
- package/dist/web/assets/database-viewer-DixWWvjx.js +0 -5
- package/dist/web/assets/gitGraph-HDMCJU4V-BdPTuzO3.js +0 -1
- package/dist/web/assets/index-C1RBJe0a.css +0 -2
- package/dist/web/assets/index-ZFyltHwi.js +0 -27
- package/dist/web/assets/info-3K5VOQVL-MHX_1JfR.js +0 -1
- package/dist/web/assets/keybindings-store-D0C-Pq2o.js +0 -1
- package/dist/web/assets/packet-RMMSAZCW-CreFbf9A.js +0 -1
- package/dist/web/assets/pie-UPGHQEXC-CnaHXUh8.js +0 -1
- package/dist/web/assets/plus-51UQ45rf.js +0 -1
- package/dist/web/assets/radar-KQ55EAFF-UxsdRHvt.js +0 -1
- package/dist/web/assets/settings-tab-BUstSDLR.js +0 -1
- package/dist/web/assets/sql-completion-provider-tCzZfqWs.js +0 -1
- package/dist/web/assets/sql-query-editor-CMQpaOjA.js +0 -3
- package/dist/web/assets/sqlite-viewer-C7rhO4bn.js +0 -1
- package/dist/web/assets/terminal-tab-Xtj6RN0d.js +0 -1
- package/dist/web/assets/trash-2-CJYoLw7Q.js +0 -1
- package/dist/web/assets/treemap-KZPCXAKY-CBVPi4NV.js +0 -1
- package/dist/web/assets/x-BtqbfkR7.js +0 -1
- /package/dist/web/assets/{arrow-up-Dtrfv490.js → arrow-up-Rcw6_KKu.js} +0 -0
- /package/dist/web/assets/{chevron-right-BzAdxJRG.js → chevron-right-DnHIvvcy.js} +0 -0
- /package/dist/web/assets/{code-CuravVys.js → code-DGBecc50.js} +0 -0
- /package/dist/web/assets/{dist-D7KGU7Vl.js → dist-CaKCIxem.js} +0 -0
- /package/dist/web/assets/{dist-CGvx1c8C.js → dist-DGSkE2Ml.js} +0 -0
- /package/dist/web/assets/{katex-BFE6i_OH.js → katex-BuytEdO1.js} +0 -0
- /package/dist/web/assets/{lib-D_kRA9p6.js → lib-DQHnkzGy.js} +0 -0
- /package/dist/web/assets/{refresh-cw-CSFrDtiu.js → refresh-cw-LlbZDJpO.js} +0 -0
- /package/dist/web/assets/{scroll-area-BEllam7_.js → scroll-area-7H-Q_k8c.js} +0 -0
- /package/dist/web/assets/{sparkles-B0mRBy_j.js → sparkles-fWUT5Vzq.js} +0 -0
- /package/dist/web/assets/{table-Dq575bPF.js → table-tf7pRkME.js} +0 -0
- /package/dist/web/assets/{text-wrap-Cn6BNQfq.js → text-wrap-BV-R4Vvy.js} +0 -0
- /package/dist/web/assets/{use-blob-url-Hn6n1730.js → use-blob-url-e9uTXjv5.js} +0 -0
- /package/dist/web/assets/{vendor-xterm-u3AZMvTx.js → vendor-xterm-CU2c3f0A.js} +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { useState, useCallback, useRef } from "react";
|
|
2
|
+
|
|
3
|
+
export interface PendingEdit {
|
|
4
|
+
pkVal: unknown;
|
|
5
|
+
col: string;
|
|
6
|
+
newVal: unknown;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface UseGlidePendingEditsResult {
|
|
10
|
+
pendingEdits: Map<string, PendingEdit>;
|
|
11
|
+
pendingRef: React.RefObject<Map<string, PendingEdit>>;
|
|
12
|
+
addEdit: (pkVal: unknown, col: string, newVal: unknown) => void;
|
|
13
|
+
commitAll: () => Promise<void>;
|
|
14
|
+
discardAll: () => void;
|
|
15
|
+
hasPending: boolean;
|
|
16
|
+
pendingCount: number;
|
|
17
|
+
/** True after commitAll until cleared — used to clear edits on rows refresh */
|
|
18
|
+
committedRef: React.RefObject<boolean>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Tracks cell edits locally until the user explicitly saves.
|
|
23
|
+
* After commit, keeps pending values visible until rows refresh (avoids flash of stale data).
|
|
24
|
+
* Supports inline insert: edits with PK starting "__new_" are routed to onInsertRow.
|
|
25
|
+
*/
|
|
26
|
+
export function useGlidePendingEdits(
|
|
27
|
+
pkCol: string | null,
|
|
28
|
+
onCellUpdate: (pkCol: string, pkVal: unknown, col: string, val: unknown) => void,
|
|
29
|
+
onInsertRow?: (values: Record<string, unknown>) => Promise<void>,
|
|
30
|
+
): UseGlidePendingEditsResult {
|
|
31
|
+
const [pendingEdits, setPendingEdits] = useState<Map<string, PendingEdit>>(new Map());
|
|
32
|
+
const pendingRef = useRef(pendingEdits);
|
|
33
|
+
pendingRef.current = pendingEdits;
|
|
34
|
+
const committedRef = useRef(false);
|
|
35
|
+
|
|
36
|
+
const addEdit = useCallback((pkVal: unknown, col: string, newVal: unknown) => {
|
|
37
|
+
const key = `${pkVal}:${col}`;
|
|
38
|
+
setPendingEdits((prev) => new Map(prev).set(key, { pkVal, col, newVal }));
|
|
39
|
+
}, []);
|
|
40
|
+
|
|
41
|
+
const commitAll = useCallback(async () => {
|
|
42
|
+
if (!pkCol) return;
|
|
43
|
+
const newRows = new Map<string, Record<string, unknown>>();
|
|
44
|
+
for (const edit of pendingRef.current.values()) {
|
|
45
|
+
const pkStr = String(edit.pkVal);
|
|
46
|
+
if (pkStr.startsWith("__new_")) {
|
|
47
|
+
if (!newRows.has(pkStr)) newRows.set(pkStr, {});
|
|
48
|
+
newRows.get(pkStr)![edit.col] = edit.newVal;
|
|
49
|
+
} else {
|
|
50
|
+
onCellUpdate(pkCol, edit.pkVal, edit.col, edit.newVal);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
if (onInsertRow) {
|
|
54
|
+
for (const values of newRows.values()) {
|
|
55
|
+
await onInsertRow(values);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
committedRef.current = true;
|
|
59
|
+
// Don't clear — wait for rows prop to refresh so grid doesn't flash stale data
|
|
60
|
+
}, [pkCol, onCellUpdate, onInsertRow]);
|
|
61
|
+
|
|
62
|
+
const discardAll = useCallback(() => {
|
|
63
|
+
setPendingEdits(new Map());
|
|
64
|
+
committedRef.current = false;
|
|
65
|
+
}, []);
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
pendingEdits, pendingRef, addEdit, commitAll, discardAll,
|
|
69
|
+
hasPending: pendingEdits.size > 0, pendingCount: pendingEdits.size,
|
|
70
|
+
committedRef,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useState, useMemo } from "react";
|
|
2
|
+
|
|
3
|
+
interface UseGlideRowPinningResult {
|
|
4
|
+
/** Rows reordered: unpinned first, pinned at end (frozen via freezeTrailingRows) */
|
|
5
|
+
effectiveRows: Record<string, unknown>[];
|
|
6
|
+
/** Number of pinned rows — pass to DataEditor's freezeTrailingRows */
|
|
7
|
+
pinnedCount: number;
|
|
8
|
+
pinnedPks: Set<string>;
|
|
9
|
+
setPinnedPks: React.Dispatch<React.SetStateAction<Set<string>>>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Manages row pinning state — pinned rows placed at the end of the array
|
|
14
|
+
* so they can be frozen at the bottom via Glide's freezeTrailingRows.
|
|
15
|
+
*/
|
|
16
|
+
export function useGlideRowPinning(
|
|
17
|
+
rows: Record<string, unknown>[],
|
|
18
|
+
pkCol: string | null,
|
|
19
|
+
): UseGlideRowPinningResult {
|
|
20
|
+
const [pinnedPks, setPinnedPks] = useState<Set<string>>(new Set());
|
|
21
|
+
|
|
22
|
+
const effectiveRows = useMemo(() => {
|
|
23
|
+
if (pinnedPks.size === 0 || !pkCol) return rows;
|
|
24
|
+
const normal: Record<string, unknown>[] = [];
|
|
25
|
+
const pinned: Record<string, unknown>[] = [];
|
|
26
|
+
for (const row of rows) {
|
|
27
|
+
if (pinnedPks.has(String(row[pkCol] ?? ""))) pinned.push(row); else normal.push(row);
|
|
28
|
+
}
|
|
29
|
+
return [...normal, ...pinned];
|
|
30
|
+
}, [rows, pinnedPks, pkCol]);
|
|
31
|
+
|
|
32
|
+
const pinnedCount = pinnedPks.size;
|
|
33
|
+
|
|
34
|
+
return { effectiveRows, pinnedCount, pinnedPks, setPinnedPks };
|
|
35
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { useState, useCallback, useMemo } from "react";
|
|
2
|
+
import { CompactSelection, type GridSelection } from "@glideapps/glide-data-grid";
|
|
3
|
+
|
|
4
|
+
const EMPTY_SELECTION: GridSelection = {
|
|
5
|
+
columns: CompactSelection.empty(),
|
|
6
|
+
rows: CompactSelection.empty(),
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
interface UseGlideSelectionResult {
|
|
10
|
+
gridSelection: GridSelection;
|
|
11
|
+
onGridSelectionChange: (newSel: GridSelection) => void;
|
|
12
|
+
/** Array of selected row indices (derived from CompactSelection) */
|
|
13
|
+
selectedRowIndices: number[];
|
|
14
|
+
clearSelection: () => void;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Manages controlled selection state for Glide Data Grid.
|
|
19
|
+
* Provides row indices array for bulk operations (delete, export).
|
|
20
|
+
*/
|
|
21
|
+
export function useGlideSelection(): UseGlideSelectionResult {
|
|
22
|
+
const [gridSelection, setGridSelection] = useState<GridSelection>(EMPTY_SELECTION);
|
|
23
|
+
|
|
24
|
+
const onGridSelectionChange = useCallback((newSel: GridSelection) => {
|
|
25
|
+
setGridSelection(newSel);
|
|
26
|
+
}, []);
|
|
27
|
+
|
|
28
|
+
const selectedRowIndices = useMemo(() => {
|
|
29
|
+
const indices: number[] = [];
|
|
30
|
+
if (gridSelection.rows) {
|
|
31
|
+
for (const range of gridSelection.rows) {
|
|
32
|
+
// CompactSelection stores [start, end) ranges
|
|
33
|
+
if (Array.isArray(range)) {
|
|
34
|
+
for (let i = range[0]; i < range[1]; i++) indices.push(i);
|
|
35
|
+
} else {
|
|
36
|
+
indices.push(range);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return indices;
|
|
41
|
+
}, [gridSelection.rows]);
|
|
42
|
+
|
|
43
|
+
const clearSelection = useCallback(() => {
|
|
44
|
+
setGridSelection(EMPTY_SELECTION);
|
|
45
|
+
}, []);
|
|
46
|
+
|
|
47
|
+
return { gridSelection, onGridSelectionChange, selectedRowIndices, clearSelection };
|
|
48
|
+
}
|
|
@@ -8,13 +8,16 @@ import { usePanelStore } from "@/stores/panel-store";
|
|
|
8
8
|
import { useSettingsStore } from "@/stores/settings-store";
|
|
9
9
|
import { basename } from "@/lib/utils";
|
|
10
10
|
import { useMonacoTheme } from "@/lib/use-monaco-theme";
|
|
11
|
-
import { Loader2, FileWarning, Play, Database } from "lucide-react";
|
|
11
|
+
import { Loader2, FileWarning, Play, Database, ExternalLink, X, GripHorizontal } from "lucide-react";
|
|
12
12
|
import { EditorBreadcrumb } from "./editor-breadcrumb";
|
|
13
13
|
import { EditorToolbar } from "./editor-toolbar";
|
|
14
14
|
import { SaveAsDialog } from "./save-as-dialog";
|
|
15
15
|
import { EditorMobileToolbar } from "./editor-mobile-toolbar";
|
|
16
16
|
import { createSqlCompletionProvider, clearCompletionCache, type SchemaInfo } from "../database/sql-completion-provider";
|
|
17
17
|
import { useConnections, type Connection } from "../database/use-connections";
|
|
18
|
+
import { GlideDataGrid } from "../database/glide-data-grid";
|
|
19
|
+
import type { GridColumnSchema } from "../database/glide-grid-types";
|
|
20
|
+
import type { DbQueryResult } from "../database/use-database";
|
|
18
21
|
|
|
19
22
|
const MarkdownRenderer = lazy(() =>
|
|
20
23
|
import("@/components/shared/markdown-renderer").then((m) => ({ default: m.MarkdownRenderer }))
|
|
@@ -170,18 +173,37 @@ export const CodeEditor = memo(function CodeEditor({ metadata, tabId }: CodeEdit
|
|
|
170
173
|
return () => { completionDisposable.current?.dispose(); };
|
|
171
174
|
}, [sqlSchemaInfo]);
|
|
172
175
|
|
|
173
|
-
// Run in
|
|
176
|
+
// Run SQL inline — execute query and show results in bottom panel
|
|
174
177
|
const openTab = useTabStore((s) => s.openTab);
|
|
175
|
-
const
|
|
178
|
+
const [sqlResult, setSqlResult] = useState<DbQueryResult | null>(null);
|
|
179
|
+
const [sqlError, setSqlError] = useState<string | null>(null);
|
|
180
|
+
const [sqlLoading, setSqlLoading] = useState(false);
|
|
181
|
+
const [sqlResultSql, setSqlResultSql] = useState<string>("");
|
|
182
|
+
const runSqlInViewer = useCallback(async (sqlText: string) => {
|
|
176
183
|
if (!selectedSqlConn) return;
|
|
184
|
+
setSqlLoading(true);
|
|
185
|
+
setSqlError(null);
|
|
186
|
+
setSqlResultSql(sqlText);
|
|
187
|
+
try {
|
|
188
|
+
const result = await api.post<DbQueryResult>(`/api/db/connections/${selectedSqlConn.id}/query`, { sql: sqlText });
|
|
189
|
+
setSqlResult(result);
|
|
190
|
+
} catch (e) {
|
|
191
|
+
setSqlError((e as Error).message);
|
|
192
|
+
setSqlResult(null);
|
|
193
|
+
} finally {
|
|
194
|
+
setSqlLoading(false);
|
|
195
|
+
}
|
|
196
|
+
}, [selectedSqlConn]);
|
|
197
|
+
const openSqlResultInTab = useCallback(() => {
|
|
198
|
+
if (!selectedSqlConn || !sqlResultSql) return;
|
|
177
199
|
openTab({
|
|
178
200
|
type: "database",
|
|
179
201
|
title: `${selectedSqlConn.name} · Query`,
|
|
180
202
|
projectId: null,
|
|
181
203
|
closable: true,
|
|
182
|
-
metadata: { connectionId: selectedSqlConn.id, connectionName: selectedSqlConn.name, dbType: selectedSqlConn.type, initialSql:
|
|
204
|
+
metadata: { connectionId: selectedSqlConn.id, connectionName: selectedSqlConn.name, dbType: selectedSqlConn.type, initialSql: sqlResultSql },
|
|
183
205
|
});
|
|
184
|
-
}, [selectedSqlConn, openTab]);
|
|
206
|
+
}, [selectedSqlConn, openTab, sqlResultSql]);
|
|
185
207
|
|
|
186
208
|
const handleRunInDbViewer = useCallback(() => {
|
|
187
209
|
if (!editorRef.current || !selectedSqlConn) return;
|
|
@@ -520,7 +542,7 @@ export const CodeEditor = memo(function CodeEditor({ metadata, tabId }: CodeEdit
|
|
|
520
542
|
onClick={handleRunInDbViewer}
|
|
521
543
|
disabled={!selectedSqlConn}
|
|
522
544
|
className="p-0.5 rounded text-muted-foreground hover:text-primary disabled:opacity-30 transition-colors"
|
|
523
|
-
title="Run
|
|
545
|
+
title="Run SQL"
|
|
524
546
|
>
|
|
525
547
|
<Play className="size-3.5" />
|
|
526
548
|
</button>
|
|
@@ -583,7 +605,7 @@ export const CodeEditor = memo(function CodeEditor({ metadata, tabId }: CodeEdit
|
|
|
583
605
|
) : isMarkdown && mdMode === "preview" ? (
|
|
584
606
|
<MarkdownPreview content={content ?? ""} />
|
|
585
607
|
) : (
|
|
586
|
-
<div className="flex-1 overflow-hidden">
|
|
608
|
+
<div className="flex-1 overflow-hidden min-h-0">
|
|
587
609
|
<Editor
|
|
588
610
|
height="100%"
|
|
589
611
|
language={inlineLanguage ?? getMonacoLanguage(filePath ?? "")}
|
|
@@ -608,6 +630,16 @@ export const CodeEditor = memo(function CodeEditor({ metadata, tabId }: CodeEdit
|
|
|
608
630
|
</div>
|
|
609
631
|
)}
|
|
610
632
|
|
|
633
|
+
{/* Inline SQL result panel */}
|
|
634
|
+
{isSql && (sqlResult || sqlError || sqlLoading) && (
|
|
635
|
+
<SqlResultPanel
|
|
636
|
+
result={sqlResult} error={sqlError} loading={sqlLoading}
|
|
637
|
+
connName={selectedSqlConn?.name}
|
|
638
|
+
onClose={() => { setSqlResult(null); setSqlError(null); setSqlLoading(false); }}
|
|
639
|
+
onOpenInTab={openSqlResultInTab}
|
|
640
|
+
/>
|
|
641
|
+
)}
|
|
642
|
+
|
|
611
643
|
{/* Mobile toolbar — bottom, like terminal */}
|
|
612
644
|
{isMobile && <EditorMobileToolbar editorRef={editorRef} readOnly={inlineContent != null} />}
|
|
613
645
|
|
|
@@ -625,6 +657,93 @@ export const CodeEditor = memo(function CodeEditor({ metadata, tabId }: CodeEdit
|
|
|
625
657
|
);
|
|
626
658
|
});
|
|
627
659
|
|
|
660
|
+
const NOOP = () => {};
|
|
661
|
+
|
|
662
|
+
/** Inline SQL result panel — shows query results below the editor */
|
|
663
|
+
function SqlResultPanel({ result, error, loading, connName, onClose, onOpenInTab }: {
|
|
664
|
+
result: DbQueryResult | null;
|
|
665
|
+
error: string | null;
|
|
666
|
+
loading: boolean;
|
|
667
|
+
connName?: string;
|
|
668
|
+
onClose: () => void;
|
|
669
|
+
onOpenInTab: () => void;
|
|
670
|
+
}) {
|
|
671
|
+
const tableData = useMemo(() => (
|
|
672
|
+
result?.changeType === "select" && result.rows.length > 0
|
|
673
|
+
? { columns: result.columns, rows: result.rows, total: result.rows.length, limit: result.rows.length }
|
|
674
|
+
: null
|
|
675
|
+
), [result]);
|
|
676
|
+
|
|
677
|
+
const querySchema = useMemo<GridColumnSchema[]>(() => (
|
|
678
|
+
(result?.columns ?? []).map((c) => ({ name: c, type: "text", nullable: true, pk: false, defaultValue: null }))
|
|
679
|
+
), [result?.columns]);
|
|
680
|
+
|
|
681
|
+
const [panelHeight, setPanelHeight] = useState(250);
|
|
682
|
+
const handleDrag = useCallback((e: React.MouseEvent) => {
|
|
683
|
+
e.preventDefault();
|
|
684
|
+
const startY = e.clientY;
|
|
685
|
+
const startH = panelHeight;
|
|
686
|
+
const onMove = (ev: MouseEvent) => setPanelHeight(Math.max(80, startH + (startY - ev.clientY)));
|
|
687
|
+
const onUp = () => { document.removeEventListener("mousemove", onMove); document.removeEventListener("mouseup", onUp); };
|
|
688
|
+
document.addEventListener("mousemove", onMove);
|
|
689
|
+
document.addEventListener("mouseup", onUp);
|
|
690
|
+
}, [panelHeight]);
|
|
691
|
+
|
|
692
|
+
return (
|
|
693
|
+
<div className="shrink-0 border-t border-border flex flex-col" style={{ height: panelHeight }}>
|
|
694
|
+
{/* Resize handle */}
|
|
695
|
+
<div onMouseDown={handleDrag}
|
|
696
|
+
className="shrink-0 h-1.5 cursor-row-resize bg-border/50 hover:bg-primary/30 flex items-center justify-center transition-colors">
|
|
697
|
+
<GripHorizontal className="size-3 text-muted-foreground/50" />
|
|
698
|
+
</div>
|
|
699
|
+
{/* Title bar */}
|
|
700
|
+
<div className="flex items-center gap-2 px-2 py-1 bg-muted/50 border-b border-border shrink-0">
|
|
701
|
+
<Database className="size-3 text-muted-foreground" />
|
|
702
|
+
<span className="text-xs font-medium text-foreground truncate flex-1">
|
|
703
|
+
{connName ? `${connName} · Results` : "Query Results"}
|
|
704
|
+
{result?.executionTimeMs != null && <span className="text-muted-foreground ml-1.5 font-normal">{result.executionTimeMs}ms</span>}
|
|
705
|
+
</span>
|
|
706
|
+
<button type="button" onClick={onOpenInTab} title="Open in DB Viewer tab"
|
|
707
|
+
className="flex items-center gap-1 px-1.5 py-0.5 rounded text-[10px] text-muted-foreground hover:text-foreground hover:bg-muted transition-colors">
|
|
708
|
+
<ExternalLink className="size-3" />
|
|
709
|
+
<span className="hidden sm:inline">Open in Tab</span>
|
|
710
|
+
</button>
|
|
711
|
+
<button type="button" onClick={onClose} title="Close results"
|
|
712
|
+
className="p-0.5 rounded text-muted-foreground hover:text-foreground transition-colors">
|
|
713
|
+
<X className="size-3" />
|
|
714
|
+
</button>
|
|
715
|
+
</div>
|
|
716
|
+
|
|
717
|
+
{/* Content */}
|
|
718
|
+
<div className="flex-1 overflow-hidden min-h-0">
|
|
719
|
+
{loading && (
|
|
720
|
+
<div className="flex items-center justify-center h-full">
|
|
721
|
+
<Loader2 className="size-4 animate-spin text-muted-foreground" />
|
|
722
|
+
</div>
|
|
723
|
+
)}
|
|
724
|
+
{error && <div className="px-3 py-2 text-xs text-destructive bg-destructive/5">{error}</div>}
|
|
725
|
+
{result?.changeType === "modify" && (
|
|
726
|
+
<div className="px-3 py-2 text-xs text-green-500">
|
|
727
|
+
{result.rowsAffected} row(s) affected
|
|
728
|
+
</div>
|
|
729
|
+
)}
|
|
730
|
+
{tableData && (
|
|
731
|
+
<GlideDataGrid
|
|
732
|
+
columns={tableData.columns} rows={tableData.rows} total={tableData.total} limit={tableData.limit}
|
|
733
|
+
schema={querySchema} loading={false}
|
|
734
|
+
page={1} onPageChange={NOOP} onCellUpdate={NOOP}
|
|
735
|
+
orderBy={null} orderDir="ASC" onToggleSort={NOOP}
|
|
736
|
+
connectionName={connName}
|
|
737
|
+
/>
|
|
738
|
+
)}
|
|
739
|
+
{result?.changeType === "select" && result.rows.length === 0 && (
|
|
740
|
+
<div className="px-3 py-2 text-xs text-muted-foreground">No results</div>
|
|
741
|
+
)}
|
|
742
|
+
</div>
|
|
743
|
+
</div>
|
|
744
|
+
);
|
|
745
|
+
}
|
|
746
|
+
|
|
628
747
|
function LoadingSpinner() {
|
|
629
748
|
return <div className="flex items-center justify-center h-full"><Loader2 className="size-5 animate-spin text-text-subtle" /></div>;
|
|
630
749
|
}
|
|
@@ -67,13 +67,13 @@ export function EditorPanel({ panelId, projectName }: EditorPanelProps) {
|
|
|
67
67
|
const isActive = tab.id === panel.activeTabId;
|
|
68
68
|
if (!Component) {
|
|
69
69
|
return (
|
|
70
|
-
<div key={tab.id} className={isActive ? "
|
|
70
|
+
<div key={tab.id} className={isActive ? "absolute inset-0 flex items-center justify-center text-muted-foreground" : "hidden"}>
|
|
71
71
|
Unknown tab type: {tab.type}
|
|
72
72
|
</div>
|
|
73
73
|
);
|
|
74
74
|
}
|
|
75
75
|
return (
|
|
76
|
-
<div key={tab.id} className={isActive ?
|
|
76
|
+
<div key={tab.id} className="absolute inset-0" style={isActive ? undefined : { opacity: 0, pointerEvents: "none" }}>
|
|
77
77
|
<Suspense fallback={<div className="flex items-center justify-center h-full"><Loader2 className="size-6 animate-spin text-primary" /></div>}>
|
|
78
78
|
<Component metadata={tab.metadata} tabId={tab.id} />
|
|
79
79
|
</Suspense>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { useState, useEffect, useRef } from "react";
|
|
1
|
+
import { useState, useEffect, useRef, useCallback } from "react";
|
|
2
2
|
import { Database, Loader2, AlertCircle } from "lucide-react";
|
|
3
3
|
import { useSqlite } from "./use-sqlite";
|
|
4
4
|
import { SqliteTableList } from "./sqlite-table-list";
|
|
5
|
-
import {
|
|
5
|
+
import { GlideDataGrid } from "../database/glide-data-grid";
|
|
6
6
|
import { SqliteQueryEditor } from "./sqlite-query-editor";
|
|
7
7
|
|
|
8
8
|
interface SqliteViewerProps {
|
|
@@ -118,17 +118,26 @@ function SqliteViewerInner({
|
|
|
118
118
|
</div>
|
|
119
119
|
</div>
|
|
120
120
|
|
|
121
|
-
{/* Data grid */}
|
|
121
|
+
{/* Data grid — adapter from sqlite rowid-based API to GlideDataGrid's pk-based API */}
|
|
122
122
|
<div className={`flex-1 overflow-hidden ${queryPanelOpen ? "max-h-[60%]" : ""}`}>
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
123
|
+
{sqlite.tableData ? (
|
|
124
|
+
<GlideDataGrid
|
|
125
|
+
columns={sqlite.tableData.columns}
|
|
126
|
+
rows={sqlite.tableData.rows}
|
|
127
|
+
total={sqlite.tableData.total}
|
|
128
|
+
limit={sqlite.tableData.limit}
|
|
129
|
+
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 }))}
|
|
130
|
+
loading={sqlite.loading}
|
|
131
|
+
page={sqlite.page}
|
|
132
|
+
onPageChange={sqlite.setPage}
|
|
133
|
+
onCellUpdate={(_pkCol, pkVal, col, val) => sqlite.updateCell(pkVal as number, col, val)}
|
|
134
|
+
onRowDelete={(_pkCol, pkVal) => sqlite.deleteRow(pkVal as number)}
|
|
135
|
+
/>
|
|
136
|
+
) : (
|
|
137
|
+
<div className="flex items-center justify-center h-full text-xs text-muted-foreground">
|
|
138
|
+
{sqlite.loading ? <Loader2 className="size-4 animate-spin" /> : "Select a table"}
|
|
139
|
+
</div>
|
|
140
|
+
)}
|
|
132
141
|
</div>
|
|
133
142
|
|
|
134
143
|
{/* Query editor (collapsible) */}
|
|
@@ -2,7 +2,7 @@ import { useState, useEffect, useCallback } from "react";
|
|
|
2
2
|
import { api, projectUrl } from "@/lib/api-client";
|
|
3
3
|
|
|
4
4
|
export interface TableInfo { name: string; rowCount: number }
|
|
5
|
-
export interface ColumnInfo { cid: number; name: string; type: string; notnull: boolean; pk: boolean; dflt_value: string | null }
|
|
5
|
+
export interface ColumnInfo { cid: number; name: string; type: string; notnull: boolean; pk: boolean; dflt_value: string | null; fk?: { table: string; column: string } | null }
|
|
6
6
|
export interface QueryResult { columns: string[]; rows: Record<string, unknown>[]; rowsAffected: number; changeType: "select" | "modify"; executionTimeMs?: number }
|
|
7
7
|
interface TableData { columns: string[]; rows: Record<string, unknown>[]; total: number; page: number; limit: number }
|
|
8
8
|
|
|
@@ -147,7 +147,7 @@ export function useTerminal(
|
|
|
147
147
|
if (event.data.startsWith("{")) {
|
|
148
148
|
try {
|
|
149
149
|
const msg = JSON.parse(event.data);
|
|
150
|
-
if (msg.type === "session" || msg.type === "error" || msg.type === "exited") {
|
|
150
|
+
if (msg.type === "session" || msg.type === "error" || msg.type === "exited" || msg.type === "ping") {
|
|
151
151
|
if (msg.type === "session" && msg.id) {
|
|
152
152
|
actualSessionId.current = msg.id; // Save for reconnect
|
|
153
153
|
}
|
package/src/web/index.html
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
<link href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@400;500;600;700&family=Geist:wght@400;500;600;700&display=swap" rel="stylesheet" />
|
|
12
12
|
</head>
|
|
13
13
|
<body class="bg-[#0f1419] text-[#e5e7eb] font-sans antialiased">
|
|
14
|
+
<div id="portal" style="position: fixed; left: 0; top: 0; z-index: 9999;" /></div>
|
|
14
15
|
<div id="root"></div>
|
|
15
16
|
<script type="module" src="./main.tsx"></script>
|
|
16
17
|
</body>
|
package/test.sql
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
select * from config;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{b as t,x as n}from"./vendor-markdown-0Mxgxy0L.js";import{D as r,_ as i,b as a,c as o,d as s,f as c,g as l,h as u,m as d,p as f,s as p,u as m,v as h,x as g,y as _}from"./vendor-ui-B-89Uj8i.js";import{t as v}from"./createLucideIcon-BjHrJDVb.js";import{i as y}from"./dist-D7KGU7Vl.js";import{n as b,r as x}from"./plus-51UQ45rf.js";import{t as S}from"./input-BMvRUOr7.js";import{t as C}from"./refresh-cw-CSFrDtiu.js";import{t as w}from"./trash-2-CJYoLw7Q.js";import{i as T,t as E}from"./api-client-Dvzcc_EO.js";import{n as D}from"./utils-CTg5uAYR.js";import{a as O,h as k}from"./api-settings-D0_eiIYv.js";var A=v(`bell-off`,[[`path`,{d:`M10.268 21a2 2 0 0 0 3.464 0`,key:`vwvbt9`}],[`path`,{d:`M17 17H4a1 1 0 0 1-.74-1.673C4.59 13.956 6 12.499 6 8a6 6 0 0 1 .258-1.742`,key:`178tsu`}],[`path`,{d:`m2 2 20 20`,key:`1ooewy`}],[`path`,{d:`M8.668 3.01A6 6 0 0 1 18 8c0 2.687.77 4.653 1.707 6.05`,key:`1hqiys`}]]),j=v(`bot`,[[`path`,{d:`M12 8V4H8`,key:`hb8ula`}],[`rect`,{width:`16`,height:`12`,x:`4`,y:`8`,rx:`2`,key:`enze0r`}],[`path`,{d:`M2 14h2`,key:`vft8re`}],[`path`,{d:`M20 14h2`,key:`4cs60a`}],[`path`,{d:`M15 13v2`,key:`1xurst`}],[`path`,{d:`M9 13v2`,key:`rq6x2g`}]]),M=v(`bug`,[[`path`,{d:`M12 20v-9`,key:`1qisl0`}],[`path`,{d:`M14 7a4 4 0 0 1 4 4v3a6 6 0 0 1-12 0v-3a4 4 0 0 1 4-4z`,key:`uouzyp`}],[`path`,{d:`M14.12 3.88 16 2`,key:`qol33r`}],[`path`,{d:`M21 21a4 4 0 0 0-3.81-4`,key:`1b0z45`}],[`path`,{d:`M21 5a4 4 0 0 1-3.55 3.97`,key:`5cxbf6`}],[`path`,{d:`M22 13h-4`,key:`1jl80f`}],[`path`,{d:`M3 21a4 4 0 0 1 3.81-4`,key:`1fjd4g`}],[`path`,{d:`M3 5a4 4 0 0 0 3.55 3.97`,key:`1d7oge`}],[`path`,{d:`M6 13H2`,key:`82j7cp`}],[`path`,{d:`m8 2 1.88 1.88`,key:`fmnt4t`}],[`path`,{d:`M9 7.13V6a3 3 0 1 1 6 0v1.13`,key:`1vgav8`}]]),N=v(`lock`,[[`rect`,{width:`18`,height:`11`,x:`3`,y:`11`,rx:`2`,ry:`2`,key:`1w4ew1`}],[`path`,{d:`M7 11V7a5 5 0 0 1 10 0v4`,key:`fwvmzm`}]]),P=v(`pencil`,[[`path`,{d:`M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z`,key:`1a8usu`}],[`path`,{d:`m15 5 4 4`,key:`1mk7zo`}]]),F=e(n(),1),I=t();function L({className:e,...t}){return(0,I.jsx)(r,{"data-slot":`label`,className:D(`flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50`,e),...t})}var R=F.forwardRef(({className:e,...t},n)=>(0,I.jsx)(p,{className:D(`peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input`,e),...t,ref:n,children:(0,I.jsx)(o,{className:D(`pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0`)})}));R.displayName=p.displayName;function z({...e}){return(0,I.jsx)(l,{"data-slot":`select`,...e})}function B({...e}){return(0,I.jsx)(a,{"data-slot":`select-value`,...e})}function V({className:e,size:t=`default`,children:n,...r}){return(0,I.jsxs)(_,{"data-slot":`select-trigger`,"data-size":t,className:D(`flex w-fit items-center justify-between gap-2 rounded-md border border-input bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[placeholder]:text-muted-foreground data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground`,e),...r,children:[n,(0,I.jsx)(s,{asChild:!0,children:(0,I.jsx)(x,{className:`size-4 opacity-50`})})]})}function H({className:e,children:t,position:n=`item-aligned`,align:r=`center`,...i}){return(0,I.jsx)(u,{children:(0,I.jsxs)(m,{"data-slot":`select-content`,className:D(`relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border bg-popover text-popover-foreground shadow-md data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95`,n===`popper`&&`data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1`,e),position:n,align:r,...i,children:[(0,I.jsx)(W,{}),(0,I.jsx)(g,{className:D(`p-1`,n===`popper`&&`h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1`),children:t}),(0,I.jsx)(G,{})]})})}function U({className:e,children:t,...n}){return(0,I.jsxs)(c,{"data-slot":`select-item`,className:D(`relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2`,e),...n,children:[(0,I.jsx)(`span`,{"data-slot":`select-item-indicator`,className:`absolute right-2 flex size-3.5 items-center justify-center`,children:(0,I.jsx)(f,{children:(0,I.jsx)(y,{className:`size-4`})})}),(0,I.jsx)(d,{children:t})]})}function W({className:e,...t}){return(0,I.jsx)(h,{"data-slot":`select-scroll-up-button`,className:D(`flex cursor-default items-center justify-center py-1`,e),...t,children:(0,I.jsx)(b,{className:`size-4`})})}function G({className:e,...t}){return(0,I.jsx)(i,{"data-slot":`select-scroll-down-button`,className:D(`flex cursor-default items-center justify-center py-1`,e),...t,children:(0,I.jsx)(x,{className:`size-4`})})}var K={claude:`C`,cursor:`▶`,codex:`◆`,gemini:`G`};function q({value:e,onChange:t,projectName:n}){let[r,i]=(0,F.useState)([]),[a,o]=(0,F.useState)(!1),s=(0,F.useRef)(null),c=(0,F.useRef)(0);(0,F.useEffect)(()=>{n&&E.get(`${T(n)}/chat/providers`).then(i).catch(()=>{})},[n]),(0,F.useEffect)(()=>{if(!a)return;let e=e=>{s.current&&!s.current.contains(e.target)&&o(!1)};return document.addEventListener(`mousedown`,e),()=>document.removeEventListener(`mousedown`,e)},[a]),(0,F.useEffect)(()=>{a&&(c.current=Math.max(0,r.findIndex(t=>t.id===e)))},[a,e,r]);let l=(0,F.useCallback)(e=>{if(e.key===`Escape`){o(!1);return}if(e.key===`ArrowDown`||e.key===`ArrowUp`){e.preventDefault();let t=e.key===`ArrowDown`?1:-1;c.current=(c.current+t+r.length)%r.length,(s.current?.querySelector(`[data-idx="${c.current}"]`))?.focus()}if(e.key===`Enter`){e.preventDefault();let n=r[c.current];n&&(t(n.id),o(!1))}},[t,r]);if(r.length<=1)return null;let u=r.find(t=>t.id===e),d=K[e]||`?`;return(0,I.jsxs)(`div`,{className:`relative`,children:[(0,I.jsxs)(`button`,{type:`button`,onClick:e=>{e.stopPropagation(),o(e=>!e)},className:`inline-flex items-center gap-1 px-2 py-1 rounded-md text-[11px] text-text-subtle hover:text-text-primary hover:bg-surface-elevated transition-colors border border-transparent hover:border-border`,"aria-label":`AI Provider: ${u?.name??e}`,children:[(0,I.jsx)(`span`,{className:`inline-flex h-3.5 w-3.5 items-center justify-center rounded text-[9px] font-bold bg-surface-elevated shrink-0`,children:d}),(0,I.jsx)(`span`,{className:`max-w-[80px] truncate capitalize`,children:u?.name??e})]}),a&&(0,I.jsxs)(`div`,{ref:s,role:`listbox`,"aria-label":`AI Providers`,onKeyDown:l,onMouseDown:e=>e.stopPropagation(),onClick:e=>e.stopPropagation(),className:`absolute bottom-full left-0 mb-1 z-50 w-56 rounded-lg border border-border bg-surface shadow-lg`,children:[(0,I.jsx)(`div`,{className:`px-3 py-2 border-b border-border`,children:(0,I.jsx)(`span`,{className:`text-xs font-medium text-text-secondary`,children:`Provider`})}),(0,I.jsx)(`div`,{className:`py-1`,children:r.map((n,r)=>{let i=K[n.id]||`?`,a=n.id===e;return(0,I.jsxs)(`button`,{"data-idx":r,role:`option`,"aria-selected":a,tabIndex:0,onClick:()=>{t(n.id),o(!1)},className:`w-full flex items-center gap-3 px-3 py-2 text-left transition-colors hover:bg-surface-elevated focus:bg-surface-elevated focus:outline-none ${a?`bg-surface-elevated`:``}`,children:[(0,I.jsx)(`span`,{className:`inline-flex h-5 w-5 items-center justify-center rounded text-[11px] font-bold bg-surface-elevated text-text-subtle shrink-0`,children:i}),(0,I.jsx)(`span`,{className:`flex-1 text-sm font-medium text-text-primary capitalize`,children:n.name}),a&&(0,I.jsx)(y,{className:`size-4 shrink-0 text-primary`})]},n.id)})})]})]})}function J({providerId:e}){return(0,I.jsx)(`span`,{className:`inline-flex h-4 w-4 items-center justify-center rounded text-[10px] font-bold bg-surface-elevated text-text-subtle shrink-0`,title:e,children:K[e]||`?`})}var Y=[{value:`low`,label:`Low`},{value:`medium`,label:`Medium`},{value:`high`,label:`High`}],X=[{value:`bypassPermissions`,label:`Bypass permissions (default)`},{value:`default`,label:`Ask before edits`},{value:`acceptEdits`,label:`Edit automatically`},{value:`plan`,label:`Plan mode`}],Z={claude:`Claude`,cursor:`Cursor`,codex:`Codex`,gemini:`Gemini`};function Q({compact:e}={}){let[t,n]=(0,F.useState)(null),[r,i]=(0,F.useState)(``),[a,o]=(0,F.useState)([]),[s,c]=(0,F.useState)(!1),[l,u]=(0,F.useState)(!1),[d,f]=(0,F.useState)(null),[p,m]=(0,F.useState)(0);(0,F.useEffect)(()=>{O().then(e=>{n(e),i(e.default_provider??`claude`)}).catch(e=>f(e.message))},[]),(0,F.useEffect)(()=>{r&&(c(!0),E.get(`/api/settings/ai/providers/${r}/models`).then(o).catch(()=>o([])).finally(()=>c(!1)))},[r]);let h=t?Object.keys(t.providers).filter(e=>e!==`mock`).map(e=>({id:e,name:Z[e]??e})):[],g=t?.providers[r],_=g?.type===`agent-sdk`||!g?.type&&r===`claude`,v=async(e,i)=>{if(t){u(!0),f(null);try{n(await k({providers:{[r]:{[e]:i}}})),m(e=>e+1)}catch(e){f(e.message)}finally{u(!1)}}},y=e?`text-[11px]`:`text-sm`,b=e?`text-xs`:`text-sm`,x=e?`space-y-2`:`space-y-4`,C=e?`space-y-1.5`:`space-y-3`,w=e?`space-y-1`:`space-y-1.5`;if(!t)return(0,I.jsxs)(`div`,{className:C,children:[(0,I.jsx)(`h3`,{className:`${b} font-medium text-text-secondary`,children:`AI Settings`}),(0,I.jsx)(`p`,{className:`${y} text-text-subtle`,children:d?`Error: ${d}`:`Loading...`})]});let T=_?a:[{value:`__default__`,label:`Auto (default)`},...a];return(0,I.jsxs)(`div`,{className:x,children:[(0,I.jsx)(`h3`,{className:`${b} font-medium text-text-secondary`,children:`AI Settings`}),h.length>1&&(0,I.jsx)(`div`,{className:`flex gap-0.5 border-b border-border/50 -mx-1 px-1`,children:h.map(e=>(0,I.jsxs)(`button`,{onClick:()=>i(e.id),className:`flex items-center gap-1 px-2 py-1 text-[11px] rounded-t transition-colors ${r===e.id?`text-primary border-b-2 border-primary font-medium`:`text-text-subtle hover:text-text-secondary`}`,children:[(0,I.jsx)(J,{providerId:e.id}),(0,I.jsx)(`span`,{className:`capitalize`,children:e.name})]},e.id))}),(0,I.jsxs)(`div`,{className:C,children:[a.length>0&&(0,I.jsxs)(`div`,{className:w,children:[(0,I.jsx)(L,{htmlFor:`ai-model`,className:e?y:void 0,children:`Model`}),(0,I.jsxs)(z,{value:_?g?.model??a[0]?.value:g?.model||`__default__`,onValueChange:e=>v(`model`,e===`__default__`?void 0:e),disabled:s,children:[(0,I.jsx)(V,{id:`ai-model`,className:`w-full ${e?`h-7 text-[11px]`:``}`,children:(0,I.jsx)(B,{placeholder:s?`Loading models...`:`Select model`})}),(0,I.jsx)(H,{className:`max-h-[300px]`,children:T.map(e=>(0,I.jsx)(U,{value:e.value,children:e.label},e.value))})]})]}),_&&(0,I.jsxs)(I.Fragment,{children:[(0,I.jsxs)(`div`,{className:w,children:[(0,I.jsx)(L,{htmlFor:`ai-base-url`,className:e?y:void 0,children:`Base URL`}),(0,I.jsx)(S,{id:`ai-base-url`,type:`url`,defaultValue:g?.base_url??``,placeholder:`https://api.anthropic.com (default)`,className:e?`h-7 text-[11px]`:void 0,onBlur:e=>{v(`base_url`,e.target.value.trim()||void 0)}},`baseurl-${r}-${p}`)]}),(0,I.jsxs)(`div`,{className:w,children:[(0,I.jsx)(L,{htmlFor:`ai-api-key`,className:e?y:void 0,children:`API Key / Token`}),(0,I.jsx)(S,{id:`ai-api-key`,type:`password`,defaultValue:g?.api_key??``,placeholder:`sk-ant-... (optional, overrides accounts)`,className:e?`h-7 text-[11px] font-mono`:`font-mono`,onBlur:e=>{let t=e.target.value.trim();t.startsWith(`••••`)||v(`api_key`,t||void 0)}},`apikey-${r}-${p}`),(0,I.jsx)(`p`,{className:`${e?`text-[9px]`:`text-[11px]`} text-muted-foreground`,children:`Direct API key or OAuth token. Leave empty to use connected accounts.`})]}),(0,I.jsxs)(`div`,{className:w,children:[(0,I.jsx)(L,{htmlFor:`ai-effort`,className:e?y:void 0,children:`Effort`}),(0,I.jsxs)(z,{value:g?.effort??`high`,onValueChange:e=>v(`effort`,e),children:[(0,I.jsx)(V,{id:`ai-effort`,className:`w-full ${e?`h-7 text-[11px]`:``}`,children:(0,I.jsx)(B,{})}),(0,I.jsx)(H,{children:Y.map(e=>(0,I.jsx)(U,{value:e.value,children:e.label},e.value))})]})]}),(0,I.jsxs)(`div`,{className:w,children:[(0,I.jsx)(L,{htmlFor:`ai-max-turns`,className:e?y:void 0,children:`Max Turns (1-500)`}),(0,I.jsx)(S,{id:`ai-max-turns`,type:`number`,min:1,max:500,defaultValue:g?.max_turns??100,className:e?`h-7 text-[11px]`:void 0,onBlur:e=>{let t=parseInt(e.target.value);isNaN(t)||v(`max_turns`,t)}},`turns-${r}-${p}`)]}),(0,I.jsxs)(`div`,{className:w,children:[(0,I.jsx)(L,{htmlFor:`ai-budget`,className:e?y:void 0,children:`Max Budget (USD)`}),(0,I.jsx)(S,{id:`ai-budget`,type:`number`,step:.1,min:.01,max:50,defaultValue:g?.max_budget_usd??``,placeholder:`No limit`,className:e?`h-7 text-[11px]`:void 0,onBlur:e=>{let t=parseFloat(e.target.value);v(`max_budget_usd`,isNaN(t)?void 0:t)}},`budget-${r}-${p}`)]}),(0,I.jsxs)(`div`,{className:w,children:[(0,I.jsx)(L,{htmlFor:`ai-thinking`,className:e?y:void 0,children:`Thinking Budget (tokens)`}),(0,I.jsx)(S,{id:`ai-thinking`,type:`number`,min:0,defaultValue:g?.thinking_budget_tokens??``,placeholder:`Disabled`,className:e?`h-7 text-[11px]`:void 0,onBlur:e=>{let t=parseInt(e.target.value);v(`thinking_budget_tokens`,isNaN(t)?void 0:t)}},`thinking-${r}-${p}`)]}),(0,I.jsxs)(`div`,{className:`flex items-center justify-between gap-2`,children:[(0,I.jsxs)(`div`,{children:[(0,I.jsx)(L,{htmlFor:`ai-agent-teams`,className:e?y:void 0,children:`Agent Teams`}),(0,I.jsx)(`p`,{className:`${e?`text-[9px]`:`text-[11px]`} text-muted-foreground`,children:`Experimental. Enables multi-agent collaboration with shared tasks and messaging. Uses ~7x more tokens.`})]}),(0,I.jsx)(R,{id:`ai-agent-teams`,checked:g?.agent_teams??!1,onCheckedChange:e=>v(`agent_teams`,e)})]}),g?.agent_teams&&(0,I.jsx)($,{compact:e})]}),(0,I.jsxs)(`div`,{className:w,children:[(0,I.jsx)(L,{htmlFor:`ai-permission-mode`,className:e?y:void 0,children:`Default Permission Mode`}),(0,I.jsxs)(z,{value:g?.permission_mode??`bypassPermissions`,onValueChange:e=>v(`permission_mode`,e),children:[(0,I.jsx)(V,{id:`ai-permission-mode`,className:`w-full ${e?`h-7 text-[11px]`:``}`,children:(0,I.jsx)(B,{})}),(0,I.jsx)(H,{children:X.map(e=>(0,I.jsx)(U,{value:e.value,children:e.label},e.value))})]})]}),(0,I.jsxs)(`div`,{className:w,children:[(0,I.jsx)(L,{htmlFor:`ai-system-prompt`,className:e?y:void 0,children:`Additional Instructions`}),(0,I.jsx)(`textarea`,{id:`ai-system-prompt`,rows:e?3:4,defaultValue:g?.system_prompt??``,placeholder:`Enter additional instructions for ${r}...`,className:`w-full rounded-md border border-input bg-background px-3 py-2 ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ${e?`text-[11px]`:`text-sm`}`,onBlur:e=>{v(`system_prompt`,e.target.value.trim()||void 0)}},`sysprompt-${r}-${p}`)]})]}),l&&(0,I.jsx)(`p`,{className:`text-xs text-text-subtle`,children:`Saving...`}),d&&(0,I.jsx)(`p`,{className:`text-xs text-red-500`,children:d})]})}function $({compact:e}){let[t,n]=(0,F.useState)([]),[r,i]=(0,F.useState)(!1),[a,o]=(0,F.useState)(null),s=(0,F.useCallback)(async()=>{i(!0);try{n(await E.get(`/api/teams`)??[])}catch{}i(!1)},[]);(0,F.useEffect)(()=>{s()},[s]);let c=async e=>{try{await E.del(`/api/teams/${encodeURIComponent(e)}`),n(t=>t.filter(t=>t.name!==e)),o(null)}catch{}};return t.length===0&&!r?null:(0,I.jsxs)(`div`,{className:`space-y-1.5`,children:[(0,I.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,I.jsxs)(L,{className:e?`text-[11px]`:void 0,children:[`Teams (`,t.length,`)`]}),(0,I.jsx)(`button`,{onClick:s,className:`text-text-subtle hover:text-foreground p-1`,"aria-label":`Refresh teams`,children:(0,I.jsx)(C,{className:`size-3 ${r?`animate-spin`:``}`})})]}),t.map(e=>(0,I.jsxs)(`div`,{className:`flex items-center justify-between p-2 rounded bg-surface-elevated text-xs`,children:[(0,I.jsxs)(`div`,{className:`min-w-0`,children:[(0,I.jsx)(`div`,{className:`font-medium truncate`,children:e.name}),e.description&&(0,I.jsx)(`div`,{className:`text-text-subtle truncate`,children:e.description}),(0,I.jsxs)(`div`,{className:`text-text-subtle`,children:[e.members?.length??e.memberCount??0,` members`,e.createdAt?` · ${new Date(e.createdAt).toLocaleDateString()}`:``]})]}),a===e.name?(0,I.jsxs)(`div`,{className:`flex gap-1 shrink-0 ml-2`,children:[(0,I.jsx)(`button`,{onClick:()=>c(e.name),className:`px-2 py-1 bg-red-600 text-white rounded text-[10px]`,children:`Delete`}),(0,I.jsx)(`button`,{onClick:()=>o(null),className:`px-2 py-1 bg-zinc-600 text-white rounded text-[10px]`,children:`Cancel`})]}):(0,I.jsx)(`button`,{onClick:()=>o(e.name),className:`shrink-0 text-text-subtle hover:text-red-500 p-1 ml-2`,"aria-label":`Delete team ${e.name}`,children:(0,I.jsx)(w,{className:`size-3.5`})})]},e.name))]})}export{H as a,B as c,P as d,N as f,A as h,z as i,R as l,j as m,J as n,U as o,M as p,q as r,V as s,Q as t,L as u};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{W as e}from"./vendor-mermaid-CMiurk2b.js";export{e as createArchitectureServices};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/markdown-renderer-CHWA0KAo.js","assets/rolldown-runtime-FhOqtrmT.js","assets/index-ZFyltHwi.js","assets/vendor-mermaid-CMiurk2b.js","assets/vendor-ui-B-89Uj8i.js","assets/vendor-markdown-0Mxgxy0L.js","assets/input-BMvRUOr7.js","assets/utils-CTg5uAYR.js","assets/createLucideIcon-BjHrJDVb.js","assets/x-BtqbfkR7.js","assets/settings-store-BHBb62gq.js","assets/react-GqWghJ-L.js","assets/api-client-Dvzcc_EO.js","assets/scroll-area-BEllam7_.js","assets/ai-settings-section-CHgpQ_OP.js","assets/dist-D7KGU7Vl.js","assets/plus-51UQ45rf.js","assets/refresh-cw-CSFrDtiu.js","assets/trash-2-CJYoLw7Q.js","assets/api-settings-D0_eiIYv.js","assets/chevron-right-BzAdxJRG.js","assets/database-DCT0OjgQ.js","assets/file-store-BrbCNyLm.js","assets/tab-store-0rGchMXr.js","assets/index-C1RBJe0a.css","assets/csv-preview-D5lmgVEy.js","assets/lib-D_kRA9p6.js","assets/arrow-up-Dtrfv490.js","assets/csv-parser-DO0dz4x_.js","assets/image-preview-CbFFD9BS.js","assets/file-exclamation-point-Baz81y5z.js","assets/use-blob-url-Hn6n1730.js","assets/pdf-preview-DQMdjqa2.js","assets/video-preview-BLI_RruT.js","assets/audio-preview-DQbX8gfL.js"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{o as e}from"./rolldown-runtime-FhOqtrmT.js";import{b as t,x as n}from"./vendor-markdown-0Mxgxy0L.js";import"./vendor-ui-B-89Uj8i.js";import{t as r}from"./createLucideIcon-BjHrJDVb.js";import"./scroll-area-BEllam7_.js";import{t as i}from"./chevron-right-BzAdxJRG.js";import{a,l as o,n as s,o as c,r as l,s as u,t as d}from"./input-BMvRUOr7.js";import{t as f}from"./code-CuravVys.js";import{t as ee}from"./database-DCT0OjgQ.js";import{n as p,r as m,t as h}from"./x-BtqbfkR7.js";import{t as g}from"./file-exclamation-point-Baz81y5z.js";import{t as _}from"./table-Dq575bPF.js";import{t as v}from"./text-wrap-Cn6BNQfq.js";import{i as y,t as b}from"./api-client-Dvzcc_EO.js";import{n as te}from"./settings-store-BHBb62gq.js";import{G as x}from"./vendor-mermaid-CMiurk2b.js";import{t as S}from"./utils-CTg5uAYR.js";import{n as ne,t as re}from"./tab-store-0rGchMXr.js";import{r as ie,t as C}from"./file-store-BrbCNyLm.js";import{G as w,J as T,Q as ae,X as E,Y as D,Z as O,a as oe,c as se,d as k,f as A,g as j,h as ce,j as M,l as N,m as P,nt as F,o as I,p as le,q as ue,u as L,z as de}from"./index-ZFyltHwi.js";import{n as fe,t as pe}from"./use-monaco-theme-CP-vyTF8.js";import{n as me,t as he}from"./sql-completion-provider-tCzZfqWs.js";var ge=r(`redo-2`,[[`path`,{d:`m15 14 5-5-5-5`,key:`12vg1m`}],[`path`,{d:`M20 9H9.5A5.5 5.5 0 0 0 4 14.5A5.5 5.5 0 0 0 9.5 20H13`,key:`6uklza`}]]),R=e(n(),1),z=t(),_e={ts:O,tsx:O,js:O,jsx:O,py:O,rs:O,go:O,html:O,css:O,scss:O,json:ae,md:E,txt:E,yaml:D,yml:D};function ve(e,t){return t?ue:_e[e.split(`.`).pop()?.toLowerCase()??``]??T}function ye(e,t){let n=[],r=e;for(let e=0;e<t.length;e++){let i=t[e],a=t.slice(0,e+1).join(`/`),o=r.find(e=>e.name===i);if(n.push({name:i,fullPath:a,node:o??null,siblings:r}),o?.children)r=o.children;else{for(let r=e+1;r<t.length;r++)n.push({name:t[r],fullPath:t.slice(0,r+1).join(`/`),node:null,siblings:[]});break}}return n}function B(e){return[...e].sort((e,t)=>e.type===t.type?e.name.localeCompare(t.name):e.type===`directory`?-1:1)}function be({filePath:e,projectName:t,tabId:n,className:r}){let a=C(e=>e.tree),{updateTab:o,openTab:s}=re(ce(e=>({updateTab:e.updateTab,openTab:e.openTab}))),c=(0,R.useRef)(null),l=(0,R.useMemo)(()=>ye(a,e.split(`/`).filter(Boolean)),[a,e]);(0,R.useEffect)(()=>{c.current&&(c.current.scrollLeft=c.current.scrollWidth)},[l]);function u(e,r){let i=S(e);r.metaKey||r.ctrlKey?s({type:`editor`,title:i,metadata:{filePath:e,projectName:t},projectId:t,closable:!0}):o(n,{title:i,metadata:{filePath:e,projectName:t}})}return(0,z.jsx)(`div`,{ref:c,className:r,children:l.map((e,n)=>(0,z.jsxs)(`div`,{className:`flex items-center shrink-0`,children:[n>0&&(0,z.jsx)(i,{className:`size-3 text-muted-foreground shrink-0 mx-0.5`}),e.siblings.length>0?(0,z.jsx)(xe,{segment:e,isLast:n===l.length-1,projectName:t,onFileClick:u}):(0,z.jsx)(`span`,{className:`text-xs text-muted-foreground px-1 py-0.5`,children:e.name})]},e.fullPath))})}function xe({segment:e,isLast:t,projectName:n,onFileClick:r}){let i=(0,R.useMemo)(()=>B(e.siblings),[e.siblings]);return(0,z.jsxs)(se,{children:[(0,z.jsx)(P,{asChild:!0,children:(0,z.jsx)(`button`,{type:`button`,className:`text-xs px-1 py-0.5 rounded hover:bg-muted transition-colors truncate max-w-[120px] ${t?`text-foreground font-medium`:`text-muted-foreground`}`,children:e.name})}),(0,z.jsx)(N,{align:`start`,className:`max-h-[300px] p-1`,children:i.map(t=>(0,z.jsx)(V,{node:t,projectName:n,activePath:e.fullPath,onFileClick:r},t.path))})]})}function V({node:e,projectName:t,activePath:n,onFileClick:r}){let i=ve(e.name,e.type===`directory`),a=e.path===n;return e.type===`directory`&&e.children&&e.children.length>0?(0,z.jsxs)(k,{children:[(0,z.jsxs)(le,{className:`text-xs gap-1.5 ${a?`bg-muted`:``}`,children:[(0,z.jsx)(i,{className:`size-3.5 shrink-0 text-muted-foreground`}),(0,z.jsx)(`span`,{className:`truncate`,children:e.name})]}),(0,z.jsx)(A,{className:`max-h-[300px] overflow-y-auto p-1`,children:B(e.children).map(e=>(0,z.jsx)(V,{node:e,projectName:t,activePath:n,onFileClick:r},e.path))})]}):(0,z.jsxs)(L,{className:`text-xs gap-1.5 cursor-pointer ${a?`bg-muted`:``}`,onSelect:e=>{},onClick:t=>{e.type!==`directory`&&r(e.path,t)},children:[(0,z.jsx)(i,{className:`size-3.5 shrink-0 text-muted-foreground`}),(0,z.jsx)(`span`,{className:`truncate`,children:e.name})]})}function H({active:e,onClick:t,icon:n,label:r}){return(0,z.jsxs)(`button`,{type:`button`,onClick:t,className:`flex items-center gap-1 px-2 py-1 rounded text-xs transition-colors ${e?`bg-muted text-foreground`:`text-muted-foreground hover:text-foreground`}`,children:[(0,z.jsx)(n,{className:`size-3`}),(0,z.jsx)(`span`,{className:`hidden sm:inline`,children:r})]})}function Se({ext:e,mdMode:t,onMdModeChange:n,csvMode:r,onCsvModeChange:i,wordWrap:a,onToggleWordWrap:o,filePath:s,projectName:c,className:l}){return(0,z.jsxs)(`div`,{className:l,children:[(e===`md`||e===`mdx`)&&n&&(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(H,{active:t===`edit`,onClick:()=>n(`edit`),icon:f,label:`Edit`}),(0,z.jsx)(H,{active:t===`preview`,onClick:()=>n(`preview`),icon:p,label:`Preview`})]}),e===`csv`&&i&&(0,z.jsxs)(z.Fragment,{children:[(0,z.jsx)(H,{active:r===`table`,onClick:()=>i(`table`),icon:_,label:`Table`}),(0,z.jsx)(H,{active:r===`raw`,onClick:()=>i(`raw`),icon:f,label:`Raw`})]}),(0,z.jsx)(H,{active:a,onClick:o,icon:v,label:`Wrap`}),s&&c&&(0,z.jsx)(H,{active:!1,onClick:()=>j(c,s),icon:m,label:`Download`})]})}function Ce({open:e,defaultName:t,content:n,onSave:r,onCancel:i}){let[f,ee]=(0,R.useState)(t),[p,m]=(0,R.useState)(!1),[h,g]=(0,R.useState)(``),_=ie(e=>e.activeProject),v=(0,R.useCallback)(()=>{let e=f.trim();if(!e){g(`Filename cannot be empty`);return}if(/[/\\]/.test(e)){g(`Filename cannot contain / or \\`);return}g(``),m(!0)},[f]),y=(0,R.useCallback)(e=>{let t=e.includes(`\\`)?`\\`:`/`;r(e.endsWith(t)?`${e}${f.trim()}`:`${e}${t}${f.trim()}`,n)},[f,n,r]);return p?(0,z.jsx)(I,{open:!0,mode:`folder`,root:_?.path,title:`Save "${f.trim()}" to...`,onSelect:y,onCancel:()=>m(!1)}):(0,z.jsx)(s,{open:e,onOpenChange:e=>{e||i()},children:(0,z.jsxs)(l,{className:`sm:max-w-md`,children:[(0,z.jsx)(c,{children:(0,z.jsx)(u,{children:`Save As`})}),(0,z.jsxs)(`div`,{className:`flex flex-col gap-2 py-2`,children:[(0,z.jsx)(`label`,{className:`text-sm text-muted-foreground`,children:`Filename`}),(0,z.jsx)(d,{value:f,onChange:e=>{ee(e.target.value),g(``)},onKeyDown:e=>{e.key===`Enter`&&v()},placeholder:`e.g. my-file.ts`,autoFocus:!0}),h&&(0,z.jsx)(`p`,{className:`text-xs text-destructive`,children:h})]}),(0,z.jsxs)(a,{children:[(0,z.jsx)(o,{variant:`outline`,onClick:i,children:`Cancel`}),(0,z.jsx)(o,{onClick:v,children:`Choose Folder...`})]})]})})}var we=typeof window<`u`&&window.isSecureContext,U=[`(`,`)`,`{`,`}`,`[`,`]`,`<`,`>`,`;`,`:`,`=`,`"`,`'`,"`",`/`,`\\`,`_`,`#`],W=`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`,G=`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`,Te=`w-px h-5 bg-border mx-0.5 shrink-0`;function Ee({editorRef:e,readOnly:t}){let n=(0,R.useCallback)(()=>e.current,[e]),r=(0,R.useCallback)(e=>{let t=n();if(!t)return;t.focus();let r=t.getSelection();r&&t.executeEdits(`mobile-toolbar`,[{range:r,text:e}])},[n]),[i,a]=(0,R.useState)(!1),o=(0,R.useRef)(null),s=(0,R.useCallback)(async()=>{try{let e=await navigator.clipboard.readText();e&&r(e)}catch{}},[r]),c=(0,R.useCallback)(()=>{a(!0),requestAnimationFrame(()=>o.current?.focus())},[]),l=(0,R.useCallback)(e=>{e.preventDefault();let t=e.clipboardData.getData(`text/plain`);t&&(a(!1),r(t))},[r]),u=(0,R.useCallback)(()=>{let e=n();e&&(e.focus(),e.trigger(`mobile-toolbar`,`undo`,null))},[n]),d=(0,R.useCallback)(()=>{let e=n();e&&(e.focus(),e.trigger(`mobile-toolbar`,`redo`,null))},[n]),f=(0,R.useCallback)(()=>{let e=n();e&&(e.focus(),e.trigger(`mobile-toolbar`,`tab`,null))},[n]);return t?null:(0,z.jsxs)(`div`,{className:`shrink-0 border-t border-border bg-surface`,children:[!we&&i&&(0,z.jsxs)(`div`,{className:`flex items-center gap-2 px-2 py-1.5 border-b border-border bg-muted/50`,children:[(0,z.jsx)(`textarea`,{ref:o,onPaste:l,placeholder:`Long-press here → Paste`,className:`flex-1 h-8 rounded border border-border bg-background text-foreground text-xs px-2 py-1.5 resize-none focus:outline-none focus:ring-1 focus:ring-primary`}),(0,z.jsx)(`button`,{type:`button`,onClick:()=>a(!1),className:`p-1.5 rounded text-muted-foreground active:bg-muted transition-colors`,children:(0,z.jsx)(h,{size:14})})]}),(0,z.jsxs)(`div`,{className:`flex items-center gap-1 px-2 py-1.5 overflow-x-auto`,children:[(0,z.jsx)(`button`,{type:`button`,onClick:we?s:c,className:W,title:`Paste`,children:(0,z.jsx)(F,{size:14})}),(0,z.jsx)(`button`,{type:`button`,onClick:u,className:W,title:`Undo`,children:(0,z.jsx)(M,{size:14})}),(0,z.jsx)(`button`,{type:`button`,onClick:d,className:W,title:`Redo`,children:(0,z.jsx)(ge,{size:14})}),(0,z.jsx)(`div`,{className:Te}),(0,z.jsx)(`button`,{type:`button`,onClick:f,className:G,children:`Tab`}),(0,z.jsx)(`div`,{className:Te}),U.map(e=>(0,z.jsx)(`button`,{type:`button`,onClick:()=>r(e),className:G,children:e},e))]})]})}var K=(0,R.lazy)(()=>x(()=>import(`./markdown-renderer-CHWA0KAo.js`).then(e=>({default:e.MarkdownRenderer})),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24]))),De=(0,R.lazy)(()=>x(()=>import(`./csv-preview-D5lmgVEy.js`).then(e=>({default:e.CsvPreview})),__vite__mapDeps([25,1,4,5,26,8,27,28]))),Oe=(0,R.lazy)(()=>x(()=>import(`./image-preview-CbFFD9BS.js`).then(e=>({default:e.ImagePreview})),__vite__mapDeps([29,2,1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,30,31]))),ke=(0,R.lazy)(()=>x(()=>import(`./pdf-preview-DQMdjqa2.js`).then(e=>({default:e.PdfPreview})),__vite__mapDeps([32,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,30,31]))),Ae=(0,R.lazy)(()=>x(()=>import(`./video-preview-BLI_RruT.js`).then(e=>({default:e.VideoPreview})),__vite__mapDeps([33,2,1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,30,31]))),je=(0,R.lazy)(()=>x(()=>import(`./audio-preview-DQbX8gfL.js`).then(e=>({default:e.AudioPreview})),__vite__mapDeps([34,2,1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,30,31]))),Me=new Set([`png`,`jpg`,`jpeg`,`gif`,`webp`,`svg`,`ico`]),Ne=new Set([`mp4`,`webm`,`mov`,`ogg`,`avi`,`mkv`]),Pe=new Set([`mp3`,`wav`,`flac`,`aac`,`m4a`,`wma`]),Fe=new Set([`db`,`sqlite`,`sqlite3`]);function Ie(e){return e.split(`.`).pop()?.toLowerCase()??``}function Le(e){return{js:`javascript`,jsx:`javascript`,ts:`typescript`,tsx:`typescript`,py:`python`,html:`html`,css:`css`,scss:`scss`,json:`json`,md:`markdown`,mdx:`markdown`,yaml:`yaml`,yml:`yaml`,sh:`shell`,bash:`shell`,sql:`sql`}[Ie(e)]??`plaintext`}var q=(0,R.memo)(function({metadata:e,tabId:t}){let n=e?.filePath,r=e?.projectName,i=e?.inlineContent,a=e?.inlineLanguage,[o,s]=(0,R.useState)(i??null),[c,l]=(0,R.useState)(`utf-8`),[u,d]=(0,R.useState)(!0),[f,p]=(0,R.useState)(null),[m,h]=(0,R.useState)(!1),_=(0,R.useRef)(null),v=(0,R.useRef)(``),x=(0,R.useRef)(null),{tabs:ie,updateTab:C}=re(ce(e=>({tabs:e.tabs,updateTab:e.updateTab}))),{wordWrap:T,toggleWordWrap:ae}=te(ce(e=>({wordWrap:e.wordWrap,toggleWordWrap:e.toggleWordWrap}))),E=pe(),D=e?.isUntitled===!0,O=e?.unsavedContent,[se,k]=(0,R.useState)(!1),A=ie.find(e=>e.id===t),j=n?Ie(n):``,M=Me.has(j),N=j===`pdf`,P=Ne.has(j),F=Pe.has(j),I=Fe.has(j),le=j===`md`||j===`mdx`,ue=j===`csv`,L=j===`sql`,[ge,_e]=(0,R.useState)(`preview`),[ve,ye]=(0,R.useState)(`table`),{connections:B,cachedTables:xe,refreshTables:V}=oe(),[H,we]=(0,R.useState)(()=>{if(!L||!n)return null;let e=localStorage.getItem(`ppm:sql-conn:${n}`);return e?Number(e):null}),U=(0,R.useRef)(null),W=(0,R.useRef)(null),G=(0,R.useMemo)(()=>B.find(e=>e.id===H)??null,[B,H]),Te=i!=null&&(a===`json`||a===`xml`),[K,q]=(0,R.useState)(!1),ze=(0,R.useCallback)(()=>{if(i)if(K)s(i),q(!1);else{let e=i.trimStart();if(a===`json`)try{s(JSON.stringify(JSON.parse(e),null,2)),q(!0)}catch{}else if(a===`xml`){let t=0;s(e.replace(/(>)(<)(\/*)/g,`$1
|
|
3
|
-
$2$3`).split(`
|
|
4
|
-
`).map(e=>{let n=e.trim();n.startsWith(`</`)&&(t=Math.max(0,t-1));let r=` `.repeat(t)+n;return n.startsWith(`<`)&&!n.startsWith(`</`)&&!n.endsWith(`/>`)&&!n.includes(`</`)&&t++,r}).join(`
|
|
5
|
-
`)),q(!0)}}},[i,a,K]),Be=(0,R.useCallback)(e=>{we(e),n&&localStorage.setItem(`ppm:sql-conn:${n}`,String(e)),V(e).catch(()=>{})},[n,V]),Y=(0,R.useMemo)(()=>{if(!L||!H)return;let e=(xe.get(H)??[]).map(e=>({name:e.tableName,schema:e.schemaName}));if(e.length!==0)return{tables:e,getColumns:async(e,t)=>b.get(`/api/db/connections/${H}/schema?table=${encodeURIComponent(e)}${t?`&schema=${encodeURIComponent(t)}`:``}`)}},[L,H,xe]);(0,R.useEffect)(()=>{if(!(!U.current||!Y))return W.current?.dispose(),he(),W.current=U.current.languages.registerCompletionItemProvider(`sql`,me(U.current,Y)),()=>{W.current?.dispose()}},[Y]);let Ve=re(e=>e.openTab),X=(0,R.useCallback)(e=>{G&&Ve({type:`database`,title:`${G.name} · Query`,projectId:null,closable:!0,metadata:{connectionId:G.id,connectionName:G.name,dbType:G.type,initialSql:e}})},[G,Ve]),He=(0,R.useCallback)(()=>{if(!x.current||!G)return;let e=x.current,t=e.getSelection();X(t&&!t.isEmpty()?e.getModel()?.getValueInRange(t)??e.getValue():e.getValue())},[G,X]),Ue=typeof window<`u`&&`ontouchstart`in window,We=(0,R.useRef)(null),[Ge,Ke]=(0,R.useState)(null);(0,R.useEffect)(()=>{if(!Ue)return;let e=window.visualViewport;if(!e)return;let t=()=>{let t=We.current;if(!t)return;let n=t.getBoundingClientRect().top;Ke(e.height-Math.max(0,n))};return e.addEventListener(`resize`,t),e.addEventListener(`scroll`,t),()=>{e.removeEventListener(`resize`,t),e.removeEventListener(`scroll`,t)}},[Ue]);let Z=(0,R.useRef)([]),qe=(0,R.useRef)(X);qe.current=X,(0,R.useEffect)(()=>()=>{Z.current.forEach(e=>e.dispose()),Z.current=[]},[]),(0,R.useEffect)(()=>{I&&t&&C(t,{type:`sqlite`})},[I,t,C]);let Q=n?/^(\/|[A-Za-z]:[/\\])/.test(n):!1;(0,R.useEffect)(()=>{if(i!=null){d(!1);return}if(D){s(O??``),v.current=O??``,d(!1),O&&h(!0);return}if(!n||!Q&&!r)return;if(M||N||P||F){d(!1);return}d(!0),p(null);let e=Q?`/api/fs/read?path=${encodeURIComponent(n)}`:`${y(r)}/files/read?path=${encodeURIComponent(n)}`;return b.get(e).then(e=>{s(e.content),e.encoding&&l(e.encoding),v.current=e.content,d(!1)}).catch(e=>{p(e instanceof Error?e.message:`Failed to load file`),d(!1)}),()=>{_.current&&clearTimeout(_.current)}},[n,r,M,N,Q,D]);let Je=(0,R.useRef)(m);Je.current=m,(0,R.useEffect)(()=>{if(!n||!r||i!=null||D)return;let e=e=>{let t=e.detail;if(t.projectName!==r||t.path!==n||Je.current)return;let i=Q?`/api/fs/read?path=${encodeURIComponent(n)}`:`${y(r)}/files/read?path=${encodeURIComponent(n)}`;b.get(i).then(e=>{e.content!==v.current&&(s(e.content),v.current=e.content,e.encoding&&l(e.encoding))}).catch(()=>{})};return window.addEventListener(`file:changed`,e),()=>window.removeEventListener(`file:changed`,e)},[n,r,Q,i,D]),(0,R.useEffect)(()=>{if(!A||i!=null)return;let t=D?`Untitled-${e?.untitledNumber??1}`:n?S(n):`Untitled`,r=m?`${t} \u25CF`:t;A.title!==r&&C(A.id,{title:r})},[m]);let Ye=(0,R.useCallback)(async e=>{if(n&&!(!Q&&!r))try{Q?await b.put(`/api/fs/write`,{path:n,content:e}):await b.put(`${y(r)}/files/write`,{path:n,content:e}),h(!1)}catch{}},[n,r,Q]);function Xe(n){let r=n??``;s(r),v.current=r,h(!0),_.current&&clearTimeout(_.current),D?_.current=setTimeout(()=>{t&&C(t,{metadata:{...e,unsavedContent:v.current}})},2e3):_.current=setTimeout(()=>Ye(v.current),1e3)}let Ze=(0,R.useCallback)(async(e,n)=>{try{if(_.current&&clearTimeout(_.current),await b.put(`/api/fs/write`,{path:e,content:n}),t){let{closeTab:n,openTab:r}=ne.getState();n(t),r({type:`editor`,title:S(e),projectId:null,metadata:{filePath:e},closable:!0})}h(!1),k(!1)}catch{}},[t]),$=e?.lineNumber,Qe=(0,R.useCallback)((e,t)=>{if(x.current=e,U.current=t,$&&$>0&&setTimeout(()=>{e.revealLineInCenter($),e.setPosition({lineNumber:$,column:1}),e.focus()},100),D&&e.addCommand(t.KeyMod.CtrlCmd|t.KeyCode.KeyS,()=>k(!0)),e.addCommand(t.KeyMod.Alt|t.KeyCode.KeyZ,()=>te.getState().toggleWordWrap()),t.languages.typescript.typescriptDefaults.setDiagnosticsOptions({noSemanticValidation:!0,noSyntaxValidation:!0,noSuggestionDiagnostics:!0}),t.languages.typescript.javascriptDefaults.setDiagnosticsOptions({noSemanticValidation:!0,noSyntaxValidation:!0,noSuggestionDiagnostics:!0}),Y&&(W.current?.dispose(),W.current=t.languages.registerCompletionItemProvider(`sql`,me(t,Y))),L){Z.current.forEach(e=>e.dispose()),Z.current=[];let n=e.getModel(),r=e.addCommand(0,(e,t)=>{t&&qe.current(t)});if(r&&n){let e=t.languages.registerCodeLensProvider(`sql`,{provideCodeLenses:e=>{if(e!==n)return{lenses:[],dispose:()=>{}};let t=[],i=e.getValue().split(`
|
|
6
|
-
`),a=-1,o=[],s=!1,c=(e,n)=>{let i=n.trim();!i||i.startsWith(`--`)||t.push({range:{startLineNumber:e,startColumn:1,endLineNumber:e,endColumn:1},command:{id:r,title:`▷ Run`,arguments:[i]}})};for(let e=0;e<i.length;e++){let t=i[e].trim();if(a===-1){if(!t||t.startsWith(`--`))continue;a=e+1,o=[]}o.push(i[e]),(t.match(/\$\$/g)||[]).length%2==1&&(s=!s),!s&&t.endsWith(`;`)&&(c(a,o.join(`
|
|
7
|
-
`)),a=-1,o=[])}return a>0&&o.join(``).trim()&&c(a,o.join(`
|
|
8
|
-
`)),{lenses:t,dispose:()=>{}}}});Z.current.push(e)}}},[Y]);if(!i&&!D&&(!n||!Q&&!r))return(0,z.jsx)(`div`,{className:`flex items-center justify-center h-full text-text-secondary text-sm`,children:`No file selected.`});if(u)return(0,z.jsxs)(`div`,{className:`flex items-center justify-center h-full gap-2 text-text-secondary`,children:[(0,z.jsx)(w,{className:`size-5 animate-spin`}),(0,z.jsx)(`span`,{className:`text-sm`,children:`Loading file...`})]});if(f)return(0,z.jsx)(`div`,{className:`flex items-center justify-center h-full text-error text-sm`,children:f});if(M)return(0,z.jsx)(R.Suspense,{fallback:(0,z.jsx)(J,{}),children:(0,z.jsx)(Oe,{filePath:n,projectName:r})});if(N)return(0,z.jsx)(R.Suspense,{fallback:(0,z.jsx)(J,{}),children:(0,z.jsx)(ke,{filePath:n,projectName:r})});if(P)return(0,z.jsx)(R.Suspense,{fallback:(0,z.jsx)(J,{}),children:(0,z.jsx)(Ae,{filePath:n,projectName:r})});if(F)return(0,z.jsx)(R.Suspense,{fallback:(0,z.jsx)(J,{}),children:(0,z.jsx)(je,{filePath:n,projectName:r})});if(c===`base64`)return(0,z.jsxs)(`div`,{className:`flex flex-col items-center justify-center h-full gap-3 text-text-secondary`,children:[(0,z.jsx)(g,{className:`size-10 text-text-subtle`}),(0,z.jsx)(`p`,{className:`text-sm`,children:`This file is a binary format and cannot be displayed.`}),(0,z.jsx)(`p`,{className:`text-xs text-text-subtle`,children:n})]});let $e=L?(0,z.jsxs)(`div`,{className:`shrink-0 flex items-center gap-1 px-2 border-l border-border`,children:[(0,z.jsx)(ee,{className:`size-3 text-muted-foreground`}),(0,z.jsxs)(`select`,{value:H??``,onChange:e=>{let t=Number(e.target.value);t&&Be(t)},className:`h-5 text-[10px] bg-transparent border border-border rounded px-1 text-foreground outline-none max-w-[140px]`,title:`Select connection for autocomplete`,children:[(0,z.jsx)(`option`,{value:``,children:`Connection…`}),B.map(e=>(0,z.jsx)(`option`,{value:e.id,children:e.name},e.id))]}),(0,z.jsx)(`button`,{type:`button`,onClick:He,disabled:!G,className:`p-0.5 rounded text-muted-foreground hover:text-primary disabled:opacity-30 transition-colors`,title:`Run all in DB Viewer`,children:(0,z.jsx)(de,{className:`size-3.5`})})]}):null;return(0,z.jsxs)(`div`,{ref:We,className:`flex flex-col h-full w-full overflow-hidden`,style:Ge?{height:`${Ge}px`,maxHeight:`${Ge}px`}:void 0,children:[i!=null&&Te&&(0,z.jsx)(`div`,{className:`flex items-center h-7 border-b border-border bg-background shrink-0 px-2 gap-2`,children:(0,z.jsx)(`button`,{type:`button`,onClick:ze,className:`text-[10px] px-2 py-0.5 rounded border border-border hover:bg-muted transition-colors text-foreground`,children:K?`Raw`:`Beautify`})}),n&&r&&t&&(0,z.jsxs)(`div`,{className:`hidden md:flex items-center h-7 border-b border-border bg-background shrink-0`,children:[(0,z.jsx)(be,{filePath:n,projectName:r,tabId:t,className:`flex items-center flex-1 min-w-0 overflow-x-auto scrollbar-none px-2 gap-0.5`}),$e,(0,z.jsx)(Se,{ext:j,mdMode:ge,onMdModeChange:_e,csvMode:ve,onCsvModeChange:ye,wordWrap:T,onToggleWordWrap:ae,filePath:n,projectName:r,className:`shrink-0 flex items-center gap-1 px-2`})]}),L&&(!r||!t)&&(0,z.jsxs)(`div`,{className:`hidden md:flex items-center h-7 border-b border-border bg-background shrink-0 px-2`,children:[(0,z.jsx)(`span`,{className:`text-xs text-muted-foreground truncate flex-1`,children:n?S(n):`SQL`}),$e]}),ue&&ve===`table`?(0,z.jsx)(R.Suspense,{fallback:(0,z.jsx)(`div`,{className:`flex items-center justify-center h-full`,children:(0,z.jsx)(w,{className:`size-5 animate-spin text-text-subtle`})}),children:(0,z.jsx)(De,{content:o??``,onContentChange:Xe,wordWrap:T})}):le&&ge===`preview`?(0,z.jsx)(Re,{content:o??``}):(0,z.jsx)(`div`,{className:`flex-1 overflow-hidden`,children:(0,z.jsx)(fe,{height:`100%`,language:a??Le(n??``),value:o??``,onChange:i==null?Xe:void 0,onMount:Qe,theme:E,options:{fontSize:13,fontFamily:`Menlo, Monaco, Consolas, monospace`,wordWrap:T?`on`:`off`,minimap:{enabled:!1},scrollBeyondLastLine:!1,automaticLayout:!0,lineNumbers:`on`,folding:!0,bracketPairColorization:{enabled:!0},readOnly:i!=null},loading:(0,z.jsx)(w,{className:`size-5 animate-spin text-text-subtle`})})}),Ue&&(0,z.jsx)(Ee,{editorRef:x,readOnly:i!=null}),se&&(0,z.jsx)(Ce,{open:se,defaultName:`Untitled-${e?.untitledNumber??1}`,content:v.current,onSave:Ze,onCancel:()=>k(!1)})]})});function J(){return(0,z.jsx)(`div`,{className:`flex items-center justify-center h-full`,children:(0,z.jsx)(w,{className:`size-5 animate-spin text-text-subtle`})})}function Re({content:e}){return(0,z.jsx)(R.Suspense,{fallback:(0,z.jsx)(`div`,{className:`animate-pulse h-4 bg-muted rounded m-4`}),children:(0,z.jsx)(K,{content:e,className:`flex-1 overflow-auto p-4`})})}export{q as CodeEditor};
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
var e=function(e){return e[e.FIELD_START=0]=`FIELD_START`,e[e.UNQUOTED=1]=`UNQUOTED`,e[e.QUOTED=2]=`QUOTED`,e[e.QUOTE_IN_QUOTED=3]=`QUOTE_IN_QUOTED`,e}(e||{});function t(t){let n=[],r=[],i=``,a=e.FIELD_START;for(let o=0;o<t.length;o++){let s=t[o];switch(a){case e.FIELD_START:s===`"`?a=e.QUOTED:s===`,`?(r.push(i),i=``):s===`\r`||(s===`
|
|
2
|
-
`?(r.push(i),i=``,n.push(r),r=[]):(i+=s,a=e.UNQUOTED));break;case e.UNQUOTED:s===`,`?(r.push(i),i=``,a=e.FIELD_START):s===`\r`||(s===`
|
|
3
|
-
`?(r.push(i),i=``,n.push(r),r=[],a=e.FIELD_START):i+=s);break;case e.QUOTED:s===`"`?a=e.QUOTE_IN_QUOTED:i+=s;break;case e.QUOTE_IN_QUOTED:s===`"`?(i+=`"`,a=e.QUOTED):s===`,`?(r.push(i),i=``,a=e.FIELD_START):s===`\r`||(s===`
|
|
4
|
-
`?(r.push(i),i=``,n.push(r),r=[],a=e.FIELD_START):(i+=s,a=e.UNQUOTED));break}}if((i||r.length>0)&&(r.push(i),n.push(r)),n.length===0)return{headers:[],rows:[]};let o=n[0],s=n.slice(1),c=o.length;for(let e=0;e<s.length;e++){let t=s[e];if(t.length<c)for(;t.length<c;)t.push(``);else t.length>c&&(s[e]=t.slice(0,c))}return{headers:o,rows:s}}function n(e,t){let n=e=>e.includes(`,`)||e.includes(`"`)||e.includes(`
|
|
5
|
-
`)?`"${e.replace(/"/g,`""`)}"`:e,r=[e.map(n).join(`,`)];for(let e of t)r.push(e.map(n).join(`,`));return r.join(`
|
|
6
|
-
`)}export{n,t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./createLucideIcon-BjHrJDVb.js";var t=e(`database`,[[`ellipse`,{cx:`12`,cy:`5`,rx:`9`,ry:`3`,key:`msslwz`}],[`path`,{d:`M3 5V19A9 3 0 0 0 21 19V5`,key:`1wlel7`}],[`path`,{d:`M3 12A9 3 0 0 0 21 12`,key:`mv7ke4`}]]);export{t};
|