@sqlrooms/sql-editor 0.7.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +210 -92
- package/dist/SqlEditor.d.ts.map +1 -1
- package/dist/SqlEditor.js +5 -5
- package/dist/SqlEditor.js.map +1 -1
- package/dist/SqlEditorModal.js +1 -1
- package/dist/SqlEditorModal.js.map +1 -1
- package/dist/SqlEditorSlice.js +10 -10
- package/dist/SqlEditorSlice.js.map +1 -1
- package/dist/SqlQueryDataSourcesPanel.js +3 -3
- package/dist/SqlQueryDataSourcesPanel.js.map +1 -1
- package/dist/TablesList.js +2 -2
- package/dist/TablesList.js.map +1 -1
- package/dist/hooks/useQueryTabManagement.d.ts.map +1 -1
- package/dist/hooks/useQueryTabManagement.js +1 -1
- package/dist/hooks/useQueryTabManagement.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
- package/dist/SqlEditorSliceConfig.d.ts +0 -53
- package/dist/SqlEditorSliceConfig.d.ts.map +0 -1
- package/dist/SqlEditorSliceConfig.js +0 -15
- package/dist/SqlEditorSliceConfig.js.map +0 -1
- package/dist/components/internal/SqlMonacoEditor.d.ts +0 -36
- package/dist/components/internal/SqlMonacoEditor.d.ts.map +0 -1
- package/dist/components/internal/SqlMonacoEditor.js +0 -219
- package/dist/components/internal/SqlMonacoEditor.js.map +0 -1
- package/dist/constants/duckdb.d.ts +0 -73
- package/dist/constants/duckdb.d.ts.map +0 -1
- package/dist/constants/duckdb.js +0 -392
- package/dist/constants/duckdb.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
This package is part of the SQLRooms framework.
|
|
2
|
+
|
|
1
3
|
# SQL Editor
|
|
2
4
|
|
|
3
5
|
A powerful SQL editor component for SQLRooms applications. This package provides React components and hooks for creating interactive SQL query interfaces with Monaco editor integration, table management, and results visualization.
|
|
@@ -22,33 +24,80 @@ npm install @sqlrooms/sql-editor
|
|
|
22
24
|
|
|
23
25
|
### Simple SQL Editor
|
|
24
26
|
|
|
27
|
+
The most basic way to use the SQL Editor with show/hide functionality:
|
|
28
|
+
|
|
25
29
|
```tsx
|
|
26
30
|
import {SqlEditor} from '@sqlrooms/sql-editor';
|
|
31
|
+
import {useDisclosure} from '@sqlrooms/ui';
|
|
32
|
+
|
|
33
|
+
function MyApp() {
|
|
34
|
+
const {isOpen, onOpen, onClose} = useDisclosure({defaultIsOpen: true});
|
|
27
35
|
|
|
28
|
-
|
|
29
|
-
|
|
36
|
+
return (
|
|
37
|
+
<div className="my-app">
|
|
38
|
+
<button onClick={isOpen ? onClose : onOpen}>
|
|
39
|
+
{isOpen ? 'Hide' : 'Show'} SQL Editor
|
|
40
|
+
</button>
|
|
30
41
|
|
|
31
|
-
|
|
42
|
+
{isOpen && <SqlEditor isOpen={true} onClose={onClose} />}
|
|
43
|
+
</div>
|
|
44
|
+
);
|
|
32
45
|
}
|
|
33
46
|
```
|
|
34
47
|
|
|
35
|
-
###
|
|
48
|
+
### SQL Editor with Custom Configuration
|
|
49
|
+
|
|
50
|
+
Using the SQL Editor with project store integration for advanced functionality:
|
|
36
51
|
|
|
37
52
|
```tsx
|
|
38
53
|
import {SqlEditor} from '@sqlrooms/sql-editor';
|
|
54
|
+
import {useProjectStore} from './store';
|
|
55
|
+
|
|
56
|
+
function AdvancedEditor() {
|
|
57
|
+
// Use the store to access SQL editor state and actions
|
|
58
|
+
const executeQuery = useProjectStore((state) => state.executeQuery);
|
|
59
|
+
const currentQuery = useProjectStore((state) => state.getCurrentQuery());
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<div className="sql-workspace">
|
|
63
|
+
<h2>SQL Workspace</h2>
|
|
64
|
+
|
|
65
|
+
<div className="tools">
|
|
66
|
+
<button onClick={() => executeQuery(currentQuery)}>Run Query</button>
|
|
67
|
+
<button onClick={() => exportResultsToCsv()}>Export Results</button>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<SqlEditor
|
|
71
|
+
isOpen={true}
|
|
72
|
+
onClose={() => {}}
|
|
73
|
+
schema="analytics"
|
|
74
|
+
initialQuery="SELECT * FROM users LIMIT 10;"
|
|
75
|
+
/>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### With Custom Documentation Panel
|
|
82
|
+
|
|
83
|
+
Adding a custom documentation panel to provide SQL reference materials:
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
import {SqlEditor} from '@sqlrooms/sql-editor';
|
|
87
|
+
import {useDisclosure} from '@sqlrooms/ui';
|
|
39
88
|
|
|
40
89
|
function AdvancedSqlEditor() {
|
|
41
|
-
const
|
|
90
|
+
const {isOpen, onClose} = useDisclosure({defaultIsOpen: true});
|
|
42
91
|
|
|
43
92
|
// Custom documentation component
|
|
44
93
|
const Documentation = () => (
|
|
45
94
|
<div className="p-4">
|
|
46
|
-
<h2 className="text-xl font-bold
|
|
95
|
+
<h2 className="mb-4 text-xl font-bold">SQL Reference</h2>
|
|
47
96
|
<div className="space-y-4">
|
|
48
97
|
<div>
|
|
49
98
|
<h3 className="text-lg font-semibold">SELECT</h3>
|
|
50
99
|
<p>Retrieves data from a table</p>
|
|
51
|
-
<pre className="bg-gray-100 p-2
|
|
100
|
+
<pre className="mt-2 rounded bg-gray-100 p-2">
|
|
52
101
|
SELECT column1, column2 FROM table_name;
|
|
53
102
|
</pre>
|
|
54
103
|
</div>
|
|
@@ -60,7 +109,7 @@ function AdvancedSqlEditor() {
|
|
|
60
109
|
return (
|
|
61
110
|
<SqlEditor
|
|
62
111
|
isOpen={isOpen}
|
|
63
|
-
onClose={
|
|
112
|
+
onClose={onClose}
|
|
64
113
|
schema="analytics"
|
|
65
114
|
documentationPanel={<Documentation />}
|
|
66
115
|
/>
|
|
@@ -68,74 +117,33 @@ function AdvancedSqlEditor() {
|
|
|
68
117
|
}
|
|
69
118
|
```
|
|
70
119
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
### SqlEditor
|
|
120
|
+
### Using SQL Monaco Editor Standalone
|
|
74
121
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
```tsx
|
|
78
|
-
import {SqlEditor} from '@sqlrooms/sql-editor';
|
|
79
|
-
|
|
80
|
-
<SqlEditor
|
|
81
|
-
isOpen={boolean}
|
|
82
|
-
onClose={() => void}
|
|
83
|
-
schema="main"
|
|
84
|
-
documentationPanel={ReactNode}
|
|
85
|
-
/>
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### SqlMonacoEditor
|
|
89
|
-
|
|
90
|
-
A standalone SQL-specific Monaco editor component.
|
|
122
|
+
For cases where you only need the editor component without the full interface:
|
|
91
123
|
|
|
92
124
|
```tsx
|
|
93
125
|
import {SqlMonacoEditor} from '@sqlrooms/sql-editor';
|
|
94
126
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
onChange={(value) => console.log(value)}
|
|
98
|
-
onExecuteQuery={() => executeQuery()}
|
|
99
|
-
/>;
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### SqlEditorModal
|
|
103
|
-
|
|
104
|
-
A modal wrapper around the SQL editor.
|
|
105
|
-
|
|
106
|
-
```tsx
|
|
107
|
-
import {SqlEditorModal} from '@sqlrooms/sql-editor';
|
|
108
|
-
|
|
109
|
-
<SqlEditorModal isOpen={isOpen} onClose={() => setIsOpen(false)} />;
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
### CreateTableModal
|
|
127
|
+
function SimpleSqlEditor() {
|
|
128
|
+
const [query, setQuery] = useState('SELECT * FROM products');
|
|
113
129
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
<CreateTableModal
|
|
120
|
-
isOpen={isOpen}
|
|
121
|
-
onClose={() => setIsOpen(false)}
|
|
122
|
-
onCreateTable={(tableName) => console.log(`Created table: ${tableName}`)}
|
|
123
|
-
tableData={queryResults}
|
|
124
|
-
/>;
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
### SqlQueryDataSourcesPanel
|
|
128
|
-
|
|
129
|
-
A panel showing available data sources for SQL queries.
|
|
130
|
-
|
|
131
|
-
```tsx
|
|
132
|
-
import {SqlQueryDataSourcesPanel} from '@sqlrooms/sql-editor';
|
|
130
|
+
const handleExecute = () => {
|
|
131
|
+
// Execute the query using your own logic
|
|
132
|
+
console.log('Executing query:', query);
|
|
133
|
+
};
|
|
133
134
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
135
|
+
return (
|
|
136
|
+
<>
|
|
137
|
+
<SqlMonacoEditor
|
|
138
|
+
value={query}
|
|
139
|
+
onChange={setQuery}
|
|
140
|
+
onExecuteQuery={handleExecute}
|
|
141
|
+
height="400px"
|
|
142
|
+
/>
|
|
143
|
+
<button onClick={handleExecute}>Execute</button>
|
|
144
|
+
</>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
139
147
|
```
|
|
140
148
|
|
|
141
149
|
## State Management
|
|
@@ -250,6 +258,139 @@ const {executeQuery, getCurrentQuery} = useStoreWithSqlEditor(useStore);
|
|
|
250
258
|
- `setSelectedQueryId(queryId: string)`: Set the selected query tab
|
|
251
259
|
- `getCurrentQuery(defaultQuery?: string)`: Get current query text
|
|
252
260
|
|
|
261
|
+
## Available Components
|
|
262
|
+
|
|
263
|
+
### SqlEditor
|
|
264
|
+
|
|
265
|
+
The main component providing a full-featured SQL editor interface.
|
|
266
|
+
|
|
267
|
+
```tsx
|
|
268
|
+
import {SqlEditor} from '@sqlrooms/sql-editor';
|
|
269
|
+
|
|
270
|
+
<SqlEditor
|
|
271
|
+
isOpen={boolean}
|
|
272
|
+
onClose={() => void}
|
|
273
|
+
schema="main"
|
|
274
|
+
documentationPanel={ReactNode}
|
|
275
|
+
/>
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### SqlMonacoEditor
|
|
279
|
+
|
|
280
|
+
A standalone SQL-specific Monaco editor component.
|
|
281
|
+
|
|
282
|
+
```tsx
|
|
283
|
+
import {SqlMonacoEditor} from '@sqlrooms/sql-editor';
|
|
284
|
+
|
|
285
|
+
<SqlMonacoEditor
|
|
286
|
+
value="SELECT * FROM users"
|
|
287
|
+
onChange={(value) => console.log(value)}
|
|
288
|
+
onExecuteQuery={() => executeQuery()}
|
|
289
|
+
/>;
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### SqlEditorModal
|
|
293
|
+
|
|
294
|
+
A modal wrapper around the SQL editor.
|
|
295
|
+
|
|
296
|
+
```tsx
|
|
297
|
+
import {SqlEditorModal} from '@sqlrooms/sql-editor';
|
|
298
|
+
import {useDisclosure} from '@sqlrooms/ui';
|
|
299
|
+
|
|
300
|
+
function EditorWithModal() {
|
|
301
|
+
const {isOpen, onOpen, onClose} = useDisclosure();
|
|
302
|
+
|
|
303
|
+
return (
|
|
304
|
+
<>
|
|
305
|
+
<button onClick={onOpen}>Open SQL Editor</button>
|
|
306
|
+
<SqlEditorModal isOpen={isOpen} onClose={onClose} />
|
|
307
|
+
</>
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### CreateTableModal
|
|
313
|
+
|
|
314
|
+
A modal for creating new tables from SQL queries.
|
|
315
|
+
|
|
316
|
+
```tsx
|
|
317
|
+
import {CreateTableModal} from '@sqlrooms/sql-editor';
|
|
318
|
+
import {useDisclosure} from '@sqlrooms/ui';
|
|
319
|
+
|
|
320
|
+
function TableCreator() {
|
|
321
|
+
const {isOpen, onOpen, onClose} = useDisclosure();
|
|
322
|
+
|
|
323
|
+
return (
|
|
324
|
+
<>
|
|
325
|
+
<button onClick={onOpen}>Create Table from Results</button>
|
|
326
|
+
<CreateTableModal
|
|
327
|
+
isOpen={isOpen}
|
|
328
|
+
onClose={onClose}
|
|
329
|
+
onCreateTable={(tableName) =>
|
|
330
|
+
console.log(`Created table: ${tableName}`)
|
|
331
|
+
}
|
|
332
|
+
tableData={queryResults}
|
|
333
|
+
/>
|
|
334
|
+
</>
|
|
335
|
+
);
|
|
336
|
+
}
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### SqlQueryDataSourcesPanel
|
|
340
|
+
|
|
341
|
+
A panel showing available data sources for SQL queries.
|
|
342
|
+
|
|
343
|
+
```tsx
|
|
344
|
+
import {SqlQueryDataSourcesPanel} from '@sqlrooms/sql-editor';
|
|
345
|
+
|
|
346
|
+
<SqlQueryDataSourcesPanel
|
|
347
|
+
onSelectTable={(tableName) => {
|
|
348
|
+
console.log(`Selected table: ${tableName}`);
|
|
349
|
+
}}
|
|
350
|
+
/>;
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
## Props
|
|
354
|
+
|
|
355
|
+
### SqlEditor Props
|
|
356
|
+
|
|
357
|
+
| Prop | Type | Default | Description |
|
|
358
|
+
| ------------------ | ----------- | --------- | -------------------------------------- |
|
|
359
|
+
| isOpen | boolean | - | Whether the editor is open |
|
|
360
|
+
| onClose | function | - | Callback when the editor is closed |
|
|
361
|
+
| schema | string | 'main' | Default schema to use for queries |
|
|
362
|
+
| documentationPanel | ReactNode | undefined | Custom documentation panel to display |
|
|
363
|
+
| initialQuery | string | '' | Initial query to display in the editor |
|
|
364
|
+
| store | StoreObject | undefined | Custom Zustand store to use (optional) |
|
|
365
|
+
|
|
366
|
+
### SqlMonacoEditor Props
|
|
367
|
+
|
|
368
|
+
| Prop | Type | Default | Description |
|
|
369
|
+
| -------------- | -------- | ------- | -------------------------------------------- |
|
|
370
|
+
| value | string | '' | The SQL query text |
|
|
371
|
+
| onChange | function | - | Callback when the query text changes |
|
|
372
|
+
| onExecuteQuery | function | - | Callback when the execute command is invoked |
|
|
373
|
+
| height | string | '300px' | Height of the editor |
|
|
374
|
+
| readOnly | boolean | false | Whether the editor is read-only |
|
|
375
|
+
| theme | string | 'dark' | Editor theme ('dark' or 'light') |
|
|
376
|
+
|
|
377
|
+
### SqlEditorModal Props
|
|
378
|
+
|
|
379
|
+
| Prop | Type | Default | Description |
|
|
380
|
+
| ------- | -------- | ------- | --------------------------------- |
|
|
381
|
+
| isOpen | boolean | - | Whether the modal is open |
|
|
382
|
+
| onClose | function | - | Callback when the modal is closed |
|
|
383
|
+
| schema | string | 'main' | Default schema to use for queries |
|
|
384
|
+
|
|
385
|
+
### CreateTableModal Props
|
|
386
|
+
|
|
387
|
+
| Prop | Type | Default | Description |
|
|
388
|
+
| ------------- | -------- | ------- | ----------------------------------------- |
|
|
389
|
+
| isOpen | boolean | - | Whether the modal is open |
|
|
390
|
+
| onClose | function | - | Callback when the modal is closed |
|
|
391
|
+
| onCreateTable | function | - | Callback when a table is created |
|
|
392
|
+
| tableData | Table | - | Apache Arrow Table data for the new table |
|
|
393
|
+
|
|
253
394
|
## Configuration
|
|
254
395
|
|
|
255
396
|
The SQL editor can be configured through the Zustand store.
|
|
@@ -265,27 +406,4 @@ const config = {
|
|
|
265
406
|
};
|
|
266
407
|
```
|
|
267
408
|
|
|
268
|
-
## Integration with DuckDB
|
|
269
|
-
|
|
270
|
-
This package integrates with `@sqlrooms/duckdb` for query execution and table management.
|
|
271
|
-
|
|
272
|
-
```tsx
|
|
273
|
-
import {getDuckDb} from '@sqlrooms/duckdb';
|
|
274
|
-
import {Table} from 'apache-arrow';
|
|
275
|
-
|
|
276
|
-
// Execute a query directly
|
|
277
|
-
async function runQuery(query: string): Promise<Table> {
|
|
278
|
-
const db = await getDuckDb();
|
|
279
|
-
return db.query(query);
|
|
280
|
-
}
|
|
281
|
-
```
|
|
282
|
-
|
|
283
|
-
## Advanced Features
|
|
284
|
-
|
|
285
|
-
- **Custom Monaco Configuration**: Customize editor settings and SQL language support
|
|
286
|
-
- **Tab Management**: Create, rename, and delete query tabs
|
|
287
|
-
- **Table Creation**: Create new tables from query results
|
|
288
|
-
- **Table Schema Inspection**: View table schemas and column types
|
|
289
|
-
- **Export Functionality**: Export query results to various formats
|
|
290
|
-
|
|
291
409
|
For more information, visit the SQLRooms documentation.
|
package/dist/SqlEditor.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SqlEditor.d.ts","sourceRoot":"","sources":["../src/SqlEditor.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAAyC,MAAM,OAAO,CAAC;AAiB9D,MAAM,MAAM,cAAc,GAAG;IAC3B,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,kDAAkD;IAClD,MAAM,EAAE,OAAO,CAAC;IAEhB,uEAAuE;IACvE,kBAAkB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAErC,0DAA0D;IAC1D,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;
|
|
1
|
+
{"version":3,"file":"SqlEditor.d.ts","sourceRoot":"","sources":["../src/SqlEditor.tsx"],"names":[],"mappings":"AAwBA,OAAO,KAAyC,MAAM,OAAO,CAAC;AAiB9D,MAAM,MAAM,cAAc,GAAG;IAC3B,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,kDAAkD;IAClD,MAAM,EAAE,OAAO,CAAC;IAEhB,uEAAuE;IACvE,kBAAkB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAErC,0DAA0D;IAC1D,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB,CAAC;AAyaF,QAAA,MAAM,SAAS,4CAA4B,CAAC;AAE5C,eAAe,SAAS,CAAC"}
|
package/dist/SqlEditor.js
CHANGED
|
@@ -31,8 +31,8 @@ const SqlEditorBase = (props) => {
|
|
|
31
31
|
// Store access - directly use the selector
|
|
32
32
|
const addOrUpdateSqlQueryDataSource = useBaseProjectStore((state) => state.project.addOrUpdateSqlQueryDataSource);
|
|
33
33
|
// Get query data and methods directly from the store
|
|
34
|
-
const queries = useStoreWithSqlEditor((s) => s.
|
|
35
|
-
const selectedQueryId = useStoreWithSqlEditor((s) => s.
|
|
34
|
+
const queries = useStoreWithSqlEditor((s) => s.config.sqlEditor.queries);
|
|
35
|
+
const selectedQueryId = useStoreWithSqlEditor((s) => s.config.sqlEditor.selectedQueryId);
|
|
36
36
|
const getCurrentQuery = useStoreWithSqlEditor((s) => s.sqlEditor.getCurrentQuery);
|
|
37
37
|
const setSelectedQueryId = useStoreWithSqlEditor((s) => s.sqlEditor.setSelectedQueryId);
|
|
38
38
|
const updateQueryText = useStoreWithSqlEditor((s) => s.sqlEditor.updateQueryText);
|
|
@@ -120,13 +120,13 @@ const SqlEditorBase = (props) => {
|
|
|
120
120
|
const handleCreateTable = useCallback(() => {
|
|
121
121
|
setCreateTableModalOpen(true);
|
|
122
122
|
}, []);
|
|
123
|
-
return (_jsxs("div", { className: "relative flex
|
|
123
|
+
return (_jsxs("div", { className: "relative flex h-full w-full flex-col overflow-hidden", children: [_jsx("div", { className: "absolute right-12 top-0", children: documentationPanel ? (_jsxs(Button, { size: "sm", variant: showDocs ? 'secondary' : 'outline', onClick: handleToggleDocs, children: [_jsx(BookOpenIcon, { className: "mr-2 h-4 w-4" }), "SQL reference"] })) : (_jsx("a", { href: "https://duckdb.org/docs/sql/introduction", target: "_blank", rel: "noreferrer", children: _jsxs(Button, { size: "sm", variant: 'outline', children: [_jsx(BookOpenIcon, { className: "mr-2 h-4 w-4" }), "SQL reference"] }) })) }), _jsxs("div", { className: "flex h-full w-full flex-col gap-2", children: [_jsx("div", { className: "mb-2 ml-1 mr-10 flex items-center gap-2", children: _jsx("h2", { className: "text-lg font-semibold", children: "SQL Editor" }) }), _jsx("div", { className: "bg-muted h-full flex-grow", children: _jsxs(ResizablePanelGroup, { direction: "horizontal", className: "h-full", children: [_jsx(ResizablePanel, { defaultSize: showDocs ? 70 : 100, children: _jsxs(ResizablePanelGroup, { direction: "vertical", className: "h-full", children: [_jsx(ResizablePanel, { defaultSize: 50, className: "flex flex-row", children: _jsxs(ResizablePanelGroup, { direction: "horizontal", children: [_jsx(ResizablePanel, { defaultSize: 20, children: tablesLoading ? (_jsx(SpinnerPane, { h: "100%" })) : tablesError ? (_jsxs("div", { className: "p-4 text-red-500", children: ["Error loading tables: ", tablesError.message] })) : (_jsx(TablesList, { schema: "information_schema", tableNames: tables, selectedTable: selectedTable, onSelect: handleSelectTable })) }), _jsx(ResizableHandle, { withHandle: true }), _jsx(ResizablePanel, { defaultSize: 80, className: "flex flex-col overflow-hidden", children: _jsxs(Tabs, { value: selectedQueryId, onValueChange: handleTabChange, className: "flex h-full flex-col overflow-hidden", children: [_jsxs("div", { className: "border-border flex items-center gap-2 border-b", children: [_jsxs(Button, { size: "sm", onClick: () => void handleRunQuery(), className: "uppercase", children: [_jsx(PlayIcon, { className: "mr-2 h-4 w-4" }), "Run"] }), _jsx(TabsList, { className: "flex-1", children: queries.map((q) => (_jsxs("div", { className: "relative", children: [_jsx(TabsTrigger, { value: q.id, className: "min-w-[60px] px-6 pr-8", children: q.name }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx("div", { className: "hover:bg-accent absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 cursor-pointer items-center justify-center rounded-sm", onClick: (e) => e.stopPropagation(), children: _jsx(MoreVerticalIcon, { className: "h-3 w-3" }) }) }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuItem, { onClick: (e) => {
|
|
124
124
|
e.stopPropagation();
|
|
125
125
|
handleStartRename(q.id, q.name, e);
|
|
126
126
|
}, children: "Rename" }), queries.length > 1 && (_jsx(DropdownMenuItem, { onClick: (e) => {
|
|
127
127
|
e.stopPropagation();
|
|
128
128
|
handleDeleteQuery(q.id, e);
|
|
129
|
-
}, className: "text-red-500", children: "Delete" }))] })] })] }, q.id))) }), _jsx(Button, { size: "icon", variant: "ghost", onClick: handleNewQuery, className: "ml-2", children: _jsx(PlusIcon, { className: "h-4 w-4" }) })] }), queries.map((q) => (_jsx(TabsContent, { value: q.id, className: "relative flex-grow data-[state=active]:flex
|
|
129
|
+
}, className: "text-red-500", children: "Delete" }))] })] })] }, q.id))) }), _jsx(Button, { size: "icon", variant: "ghost", onClick: handleNewQuery, className: "ml-2", children: _jsx(PlusIcon, { className: "h-4 w-4" }) })] }), queries.map((q) => (_jsx(TabsContent, { value: q.id, className: "relative h-full flex-grow flex-col data-[state=active]:flex", children: _jsx("div", { className: "absolute inset-0 h-full w-full flex-grow", children: _jsx(SqlMonacoEditor, { value: q.query, onChange: handleUpdateQuery, className: "h-full w-full flex-grow", options: {
|
|
130
130
|
scrollBeyondLastLine: false,
|
|
131
131
|
automaticLayout: true,
|
|
132
132
|
minimap: { enabled: false },
|
|
@@ -144,7 +144,7 @@ const SqlEditorBase = (props) => {
|
|
|
144
144
|
void fetchTables();
|
|
145
145
|
}
|
|
146
146
|
return { tableSchemas };
|
|
147
|
-
} }) }) }, q.id)))] }) })] }) }), _jsx(ResizableHandle, { withHandle: true }), _jsx(ResizablePanel, { defaultSize: 50, className: "overflow-hidden
|
|
147
|
+
} }) }) }, q.id)))] }) })] }) }), _jsx(ResizableHandle, { withHandle: true }), _jsx(ResizablePanel, { defaultSize: 50, className: "bg-muted overflow-hidden text-sm", children: loading ? (_jsx(SpinnerPane, { h: "100%" })) : selectedTable ? (_jsx(QueryDataTable, { query: `SELECT * FROM ${schema}.${escapeId(selectedTable)}` })) : error ? (_jsx("div", { className: "h-full w-full overflow-auto p-5", children: _jsx("pre", { className: "text-xs leading-tight text-red-500", children: error }) })) : resultsTableData ? (_jsxs("div", { className: "relative flex h-full w-full flex-grow flex-col overflow-hidden", children: [_jsx(DataTableVirtualized, { ...resultsTableData }), _jsxs("div", { className: "absolute bottom-0 right-0 flex gap-2", children: [_jsxs(Button, { size: "sm", disabled: !resultsTableData, onClick: handleCreateTable, children: [_jsx(PlusIcon, { className: "mr-2 h-4 w-4" }), "Create table"] }), _jsxs(Button, { size: "sm", disabled: !results, onClick: exportResults, children: [_jsx(DownloadIcon, { className: "mr-2 h-4 w-4" }), "Export"] })] })] })) : null })] }) }), showDocs && (_jsxs(_Fragment, { children: [_jsx(ResizableHandle, { withHandle: true }), _jsx(ResizablePanel, { defaultSize: 30, children: documentationPanel })] }))] }) }), _jsx(CreateTableModal, { query: lastExecutedQuery || currentQuery, isOpen: createTableModalOpen, onClose: () => setCreateTableModalOpen(false), onAddOrUpdateSqlQuery: addOrUpdateSqlQueryDataSource }), _jsx(DeleteSqlQueryModal, { isOpen: queryToDelete !== null, onClose: () => setQueryToDelete(null), onConfirm: handleConfirmDeleteQuery }), _jsx(RenameSqlQueryModal, { isOpen: queryToRename !== null, onClose: () => setQueryToRename(null), initialName: queryToRename?.name ?? '', onRename: handleFinishRename })] })] }));
|
|
148
148
|
};
|
|
149
149
|
// Wrap with React.memo to prevent unnecessary re-renders
|
|
150
150
|
const SqlEditor = React.memo(SqlEditorBase);
|
package/dist/SqlEditor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SqlEditor.js","sourceRoot":"","sources":["../src/SqlEditor.tsx"],"names":[],"mappings":"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","sourcesContent":["import {DataTableVirtualized, QueryDataTable} from '@sqlrooms/data-table';\nimport {escapeId} from '@sqlrooms/duckdb';\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n ResizableHandle,\n ResizablePanel,\n ResizablePanelGroup,\n SpinnerPane,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from '@sqlrooms/ui';\nimport {\n BookOpenIcon,\n DownloadIcon,\n MoreVerticalIcon,\n PlayIcon,\n PlusIcon,\n} from 'lucide-react';\nimport React, {useCallback, useEffect, useState} from 'react';\nimport CreateTableModal from './CreateTableModal';\nimport DeleteSqlQueryModal from './DeleteSqlQueryModal';\nimport RenameSqlQueryModal from './RenameSqlQueryModal';\nimport {useStoreWithSqlEditor} from './SqlEditorSlice';\nimport {TablesList} from './TablesList';\nimport {SqlMonacoEditor} from './SqlMonacoEditor';\nimport type * as Monaco from 'monaco-editor';\nimport {useTableManagement, useQueryExecution, useMonacoEditor} from './hooks';\nimport {useBaseProjectStore} from '@sqlrooms/project-builder';\n\n// Define the types for Monaco Editor\ntype EditorInstance = Monaco.editor.IStandaloneCodeEditor;\ntype MonacoInstance = typeof Monaco;\n\nconst DEFAULT_QUERY = '';\n\nexport type SqlEditorProps = {\n /** The database schema to use for queries. Defaults to 'main' */\n schema?: string;\n\n /** Whether the SQL editor is currently visible */\n isOpen: boolean;\n\n /** Optional component to render SQL documentation in the side panel */\n documentationPanel?: React.ReactNode;\n\n /** Callback fired when the SQL editor should be closed */\n onClose: () => void;\n};\n\n/**\n * A full-featured SQL editor component with query execution, table management, and results visualization.\n *\n * Features:\n * - Multiple query tabs with save/rename/delete functionality\n * - Query execution with results displayed in a data table\n * - Table browser showing available tables in the schema\n * - Export results to CSV\n * - Create new tables from query results\n * - Optional SQL documentation panel\n * - Keyboard shortcuts (Cmd/Ctrl + Enter to run queries)\n *\n */\nconst SqlEditorBase: React.FC<SqlEditorProps> = (props) => {\n const {schema = 'main', documentationPanel} = props;\n\n // Store access - directly use the selector\n const addOrUpdateSqlQueryDataSource = useBaseProjectStore(\n (state) => state.project.addOrUpdateSqlQueryDataSource,\n );\n\n // Get query data and methods directly from the store\n const queries = useStoreWithSqlEditor(\n (s) => s.project.config.sqlEditor.queries,\n );\n const selectedQueryId = useStoreWithSqlEditor(\n (s) => s.project.config.sqlEditor.selectedQueryId,\n );\n const getCurrentQuery = useStoreWithSqlEditor(\n (s) => s.sqlEditor.getCurrentQuery,\n );\n const setSelectedQueryId = useStoreWithSqlEditor(\n (s) => s.sqlEditor.setSelectedQueryId,\n );\n const updateQueryText = useStoreWithSqlEditor(\n (s) => s.sqlEditor.updateQueryText,\n );\n const createQueryTab = useStoreWithSqlEditor(\n (s) => s.sqlEditor.createQueryTab,\n );\n const deleteQueryTab = useStoreWithSqlEditor(\n (s) => s.sqlEditor.deleteQueryTab,\n );\n const renameQueryTab = useStoreWithSqlEditor(\n (s) => s.sqlEditor.renameQueryTab,\n );\n\n // UI state\n const [showDocs, setShowDocs] = useState(false);\n const [createTableModalOpen, setCreateTableModalOpen] = useState(false);\n const [lastExecutedQuery, setLastExecutedQuery] = useState<string>('');\n\n // Local state for modals\n const [queryToDelete, setQueryToDelete] = useState<string | null>(null);\n const [queryToRename, setQueryToRename] = useState<{\n id: string;\n name: string;\n } | null>(null);\n\n // Custom hooks\n const {\n tables,\n tablesLoading,\n tablesError,\n tableSchemas,\n selectedTable,\n fetchTables,\n handleSelectTable,\n } = useTableManagement();\n\n const {results, resultsTableData, loading, error, runQuery, exportResults} =\n useQueryExecution(schema);\n\n const {handleEditorMount, getQueryText, setRunQueryHandler} =\n useMonacoEditor();\n\n // Get the current query text\n const currentQuery = getCurrentQuery(DEFAULT_QUERY);\n\n // Handler functions for query tab management\n const handleTabChange = useCallback(\n (value: string) => {\n setSelectedQueryId(value);\n },\n [setSelectedQueryId],\n );\n\n const handleUpdateQuery = useCallback(\n (value: string | undefined) => {\n if (!value) return;\n updateQueryText(selectedQueryId, value);\n },\n [selectedQueryId, updateQueryText],\n );\n\n const handleNewQuery = useCallback(() => {\n return createQueryTab(DEFAULT_QUERY);\n }, [createQueryTab]);\n\n const handleStartRename = useCallback(\n (queryId: string, currentName: string, event: React.MouseEvent) => {\n event.preventDefault();\n setQueryToRename({id: queryId, name: currentName});\n },\n [],\n );\n\n const handleFinishRename = useCallback(\n (newName: string) => {\n if (queryToRename) {\n renameQueryTab(queryToRename.id, newName);\n }\n setQueryToRename(null);\n },\n [queryToRename, renameQueryTab],\n );\n\n const handleDeleteQuery = useCallback(\n (queryId: string, event: React.MouseEvent) => {\n event.stopPropagation();\n setQueryToDelete(queryId);\n },\n [],\n );\n\n const handleConfirmDeleteQuery = useCallback(() => {\n if (queryToDelete) {\n deleteQueryTab(queryToDelete);\n setQueryToDelete(null);\n }\n }, [queryToDelete, deleteQueryTab]);\n\n // Handle run query logic\n const handleRunQuery = useCallback(async () => {\n // Clear selected table when running a query\n handleSelectTable(undefined);\n\n // Get the query text (either selected text or the entire query)\n const queryToRun = getQueryText(selectedQueryId, currentQuery);\n\n // Store the query that's being executed\n setLastExecutedQuery(queryToRun);\n\n // Run the query and refresh tables list\n await runQuery(queryToRun);\n }, [\n handleSelectTable,\n getQueryText,\n selectedQueryId,\n currentQuery,\n runQuery,\n setLastExecutedQuery,\n ]);\n\n // Set up the run query handler reference for keyboard shortcuts\n useEffect(() => {\n setRunQueryHandler(handleRunQuery);\n }, [handleRunQuery, setRunQueryHandler]);\n\n // Check if table schemas are empty and refetch if needed\n useEffect(() => {\n if (Object.keys(tableSchemas).length === 0) {\n void fetchTables();\n }\n }, [fetchTables, tableSchemas]);\n\n // Handle toggle documentation panel\n const handleToggleDocs = useCallback(() => {\n setShowDocs(!showDocs);\n }, [showDocs]);\n\n // Handle create table from query results\n const handleCreateTable = useCallback(() => {\n setCreateTableModalOpen(true);\n }, []);\n\n return (\n <div className=\"relative flex flex-col h-full w-full overflow-hidden\">\n <div className=\"absolute right-12 top-0\">\n {documentationPanel ? (\n <Button\n size=\"sm\"\n variant={showDocs ? 'secondary' : 'outline'}\n onClick={handleToggleDocs}\n >\n <BookOpenIcon className=\"w-4 h-4 mr-2\" />\n SQL reference\n </Button>\n ) : (\n <a\n href=\"https://duckdb.org/docs/sql/introduction\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n <Button size=\"sm\" variant={'outline'}>\n <BookOpenIcon className=\"w-4 h-4 mr-2\" />\n SQL reference\n </Button>\n </a>\n )}\n </div>\n <div className=\"flex flex-col w-full gap-2 h-full\">\n <div className=\"flex items-center gap-2 ml-1 mr-10 mb-2\">\n <h2 className=\"text-lg font-semibold\">SQL Editor</h2>\n </div>\n <div className=\"flex-grow h-full bg-muted\">\n <ResizablePanelGroup direction=\"horizontal\" className=\"h-full\">\n {/* Main panel - takes full width when docs not shown, or 70% when docs shown */}\n <ResizablePanel defaultSize={showDocs ? 70 : 100}>\n <ResizablePanelGroup direction=\"vertical\" className=\"h-full\">\n <ResizablePanel defaultSize={50} className=\"flex flex-row\">\n <ResizablePanelGroup direction=\"horizontal\">\n <ResizablePanel defaultSize={20}>\n {tablesLoading ? (\n <SpinnerPane h=\"100%\" />\n ) : tablesError ? (\n <div className=\"p-4 text-red-500\">\n Error loading tables: {tablesError.message}\n </div>\n ) : (\n <TablesList\n schema=\"information_schema\"\n tableNames={tables}\n selectedTable={selectedTable}\n onSelect={handleSelectTable}\n />\n )}\n </ResizablePanel>\n <ResizableHandle withHandle />\n <ResizablePanel\n defaultSize={80}\n className=\"flex flex-col overflow-hidden\"\n >\n <Tabs\n value={selectedQueryId}\n onValueChange={handleTabChange}\n className=\"flex flex-col h-full overflow-hidden\"\n >\n <div className=\"flex items-center gap-2 border-b border-border\">\n <Button\n size=\"sm\"\n onClick={() => void handleRunQuery()}\n className=\"uppercase\"\n >\n <PlayIcon className=\"w-4 h-4 mr-2\" />\n Run\n </Button>\n <TabsList className=\"flex-1\">\n {queries.map((q: any) => (\n <div key={q.id} className=\"relative\">\n <TabsTrigger\n value={q.id}\n className=\"min-w-[60px] px-6 pr-8\"\n >\n {q.name}\n </TabsTrigger>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <div\n className=\"absolute right-0 top-1/2 -translate-y-1/2 h-6 w-6 flex items-center justify-center cursor-pointer hover:bg-accent rounded-sm\"\n onClick={(e) => e.stopPropagation()}\n >\n <MoreVerticalIcon className=\"h-3 w-3\" />\n </div>\n </DropdownMenuTrigger>\n <DropdownMenuContent>\n <DropdownMenuItem\n onClick={(e) => {\n e.stopPropagation();\n handleStartRename(q.id, q.name, e);\n }}\n >\n Rename\n </DropdownMenuItem>\n {queries.length > 1 && (\n <DropdownMenuItem\n onClick={(e) => {\n e.stopPropagation();\n handleDeleteQuery(q.id, e);\n }}\n className=\"text-red-500\"\n >\n Delete\n </DropdownMenuItem>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n ))}\n </TabsList>\n <Button\n size=\"icon\"\n variant=\"ghost\"\n onClick={handleNewQuery}\n className=\"ml-2\"\n >\n <PlusIcon className=\"h-4 w-4\" />\n </Button>\n </div>\n {queries.map((q: any) => (\n <TabsContent\n key={q.id}\n value={q.id}\n className=\"relative flex-grow data-[state=active]:flex flex-col h-full\"\n >\n <div className=\"flex-grow h-full w-full absolute inset-0\">\n <SqlMonacoEditor\n value={q.query}\n onChange={handleUpdateQuery}\n className=\"h-full w-full flex-grow\"\n options={{\n scrollBeyondLastLine: false,\n automaticLayout: true,\n minimap: {enabled: false},\n wordWrap: 'on',\n // Enable keyboard shortcuts\n quickSuggestions: true,\n suggestOnTriggerCharacters: true,\n }}\n onMount={(\n editor: EditorInstance,\n monaco: MonacoInstance,\n ) => {\n handleEditorMount(\n editor,\n monaco,\n q.id,\n handleRunQuery,\n );\n }}\n tableSchemas={tableSchemas}\n getLatestSchemas={() => {\n // If tableSchemas is empty, try to fetch tables\n if (Object.keys(tableSchemas).length === 0) {\n // We can't await here, but we can trigger the fetch\n // This will update the state for next time\n void fetchTables();\n }\n return {tableSchemas};\n }}\n />\n </div>\n </TabsContent>\n ))}\n </Tabs>\n </ResizablePanel>\n </ResizablePanelGroup>\n </ResizablePanel>\n <ResizableHandle withHandle />\n <ResizablePanel\n defaultSize={50}\n className=\"overflow-hidden bg-muted text-sm\"\n >\n {loading ? (\n <SpinnerPane h=\"100%\" />\n ) : selectedTable ? (\n <QueryDataTable\n query={`SELECT * FROM ${schema}.${escapeId(selectedTable)}`}\n />\n ) : error ? (\n <div className=\"w-full h-full p-5 overflow-auto\">\n <pre className=\"text-xs leading-tight text-red-500\">\n {error}\n </pre>\n </div>\n ) : resultsTableData ? (\n <div className=\"flex-grow overflow-hidden flex flex-col relative w-full h-full\">\n <DataTableVirtualized {...resultsTableData} />\n <div className=\"absolute bottom-0 right-0 flex gap-2\">\n <Button\n size=\"sm\"\n disabled={!resultsTableData}\n onClick={handleCreateTable}\n >\n <PlusIcon className=\"w-4 h-4 mr-2\" />\n Create table\n </Button>\n <Button\n size=\"sm\"\n disabled={!results}\n onClick={exportResults}\n >\n <DownloadIcon className=\"w-4 h-4 mr-2\" />\n Export\n </Button>\n </div>\n </div>\n ) : null}\n </ResizablePanel>\n </ResizablePanelGroup>\n </ResizablePanel>\n {showDocs && (\n <>\n <ResizableHandle withHandle />\n {/* Documentation panel - 30% width */}\n <ResizablePanel defaultSize={30}>\n {documentationPanel}\n </ResizablePanel>\n </>\n )}\n </ResizablePanelGroup>\n </div>\n <CreateTableModal\n query={lastExecutedQuery || currentQuery}\n isOpen={createTableModalOpen}\n onClose={() => setCreateTableModalOpen(false)}\n onAddOrUpdateSqlQuery={addOrUpdateSqlQueryDataSource}\n />\n <DeleteSqlQueryModal\n isOpen={queryToDelete !== null}\n onClose={() => setQueryToDelete(null)}\n onConfirm={handleConfirmDeleteQuery}\n />\n <RenameSqlQueryModal\n isOpen={queryToRename !== null}\n onClose={() => setQueryToRename(null)}\n initialName={queryToRename?.name ?? ''}\n onRename={handleFinishRename}\n />\n </div>\n </div>\n );\n};\n\n// Wrap with React.memo to prevent unnecessary re-renders\nconst SqlEditor = React.memo(SqlEditorBase);\n\nexport default SqlEditor;\n"]}
|
|
1
|
+
{"version":3,"file":"SqlEditor.js","sourceRoot":"","sources":["../src/SqlEditor.tsx"],"names":[],"mappings":"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","sourcesContent":["import {DataTableVirtualized, QueryDataTable} from '@sqlrooms/data-table';\nimport {escapeId} from '@sqlrooms/duckdb';\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n ResizableHandle,\n ResizablePanel,\n ResizablePanelGroup,\n SpinnerPane,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n} from '@sqlrooms/ui';\nimport {\n BookOpenIcon,\n DownloadIcon,\n MoreVerticalIcon,\n PlayIcon,\n PlusIcon,\n} from 'lucide-react';\nimport React, {useCallback, useEffect, useState} from 'react';\nimport CreateTableModal from './CreateTableModal';\nimport DeleteSqlQueryModal from './DeleteSqlQueryModal';\nimport RenameSqlQueryModal from './RenameSqlQueryModal';\nimport {useStoreWithSqlEditor} from './SqlEditorSlice';\nimport {TablesList} from './TablesList';\nimport {SqlMonacoEditor} from './SqlMonacoEditor';\nimport type * as Monaco from 'monaco-editor';\nimport {useTableManagement, useQueryExecution, useMonacoEditor} from './hooks';\nimport {useBaseProjectStore} from '@sqlrooms/project-builder';\n\n// Define the types for Monaco Editor\ntype EditorInstance = Monaco.editor.IStandaloneCodeEditor;\ntype MonacoInstance = typeof Monaco;\n\nconst DEFAULT_QUERY = '';\n\nexport type SqlEditorProps = {\n /** The database schema to use for queries. Defaults to 'main' */\n schema?: string;\n\n /** Whether the SQL editor is currently visible */\n isOpen: boolean;\n\n /** Optional component to render SQL documentation in the side panel */\n documentationPanel?: React.ReactNode;\n\n /** Callback fired when the SQL editor should be closed */\n onClose: () => void;\n};\n\n/**\n * A full-featured SQL editor component with query execution, table management, and results visualization.\n *\n * Features:\n * - Multiple query tabs with save/rename/delete functionality\n * - Query execution with results displayed in a data table\n * - Table browser showing available tables in the schema\n * - Export results to CSV\n * - Create new tables from query results\n * - Optional SQL documentation panel\n * - Keyboard shortcuts (Cmd/Ctrl + Enter to run queries)\n *\n */\nconst SqlEditorBase: React.FC<SqlEditorProps> = (props) => {\n const {schema = 'main', documentationPanel} = props;\n\n // Store access - directly use the selector\n const addOrUpdateSqlQueryDataSource = useBaseProjectStore(\n (state) => state.project.addOrUpdateSqlQueryDataSource,\n );\n\n // Get query data and methods directly from the store\n const queries = useStoreWithSqlEditor((s) => s.config.sqlEditor.queries);\n const selectedQueryId = useStoreWithSqlEditor(\n (s) => s.config.sqlEditor.selectedQueryId,\n );\n const getCurrentQuery = useStoreWithSqlEditor(\n (s) => s.sqlEditor.getCurrentQuery,\n );\n const setSelectedQueryId = useStoreWithSqlEditor(\n (s) => s.sqlEditor.setSelectedQueryId,\n );\n const updateQueryText = useStoreWithSqlEditor(\n (s) => s.sqlEditor.updateQueryText,\n );\n const createQueryTab = useStoreWithSqlEditor(\n (s) => s.sqlEditor.createQueryTab,\n );\n const deleteQueryTab = useStoreWithSqlEditor(\n (s) => s.sqlEditor.deleteQueryTab,\n );\n const renameQueryTab = useStoreWithSqlEditor(\n (s) => s.sqlEditor.renameQueryTab,\n );\n\n // UI state\n const [showDocs, setShowDocs] = useState(false);\n const [createTableModalOpen, setCreateTableModalOpen] = useState(false);\n const [lastExecutedQuery, setLastExecutedQuery] = useState<string>('');\n\n // Local state for modals\n const [queryToDelete, setQueryToDelete] = useState<string | null>(null);\n const [queryToRename, setQueryToRename] = useState<{\n id: string;\n name: string;\n } | null>(null);\n\n // Custom hooks\n const {\n tables,\n tablesLoading,\n tablesError,\n tableSchemas,\n selectedTable,\n fetchTables,\n handleSelectTable,\n } = useTableManagement();\n\n const {results, resultsTableData, loading, error, runQuery, exportResults} =\n useQueryExecution(schema);\n\n const {handleEditorMount, getQueryText, setRunQueryHandler} =\n useMonacoEditor();\n\n // Get the current query text\n const currentQuery = getCurrentQuery(DEFAULT_QUERY);\n\n // Handler functions for query tab management\n const handleTabChange = useCallback(\n (value: string) => {\n setSelectedQueryId(value);\n },\n [setSelectedQueryId],\n );\n\n const handleUpdateQuery = useCallback(\n (value: string | undefined) => {\n if (!value) return;\n updateQueryText(selectedQueryId, value);\n },\n [selectedQueryId, updateQueryText],\n );\n\n const handleNewQuery = useCallback(() => {\n return createQueryTab(DEFAULT_QUERY);\n }, [createQueryTab]);\n\n const handleStartRename = useCallback(\n (queryId: string, currentName: string, event: React.MouseEvent) => {\n event.preventDefault();\n setQueryToRename({id: queryId, name: currentName});\n },\n [],\n );\n\n const handleFinishRename = useCallback(\n (newName: string) => {\n if (queryToRename) {\n renameQueryTab(queryToRename.id, newName);\n }\n setQueryToRename(null);\n },\n [queryToRename, renameQueryTab],\n );\n\n const handleDeleteQuery = useCallback(\n (queryId: string, event: React.MouseEvent) => {\n event.stopPropagation();\n setQueryToDelete(queryId);\n },\n [],\n );\n\n const handleConfirmDeleteQuery = useCallback(() => {\n if (queryToDelete) {\n deleteQueryTab(queryToDelete);\n setQueryToDelete(null);\n }\n }, [queryToDelete, deleteQueryTab]);\n\n // Handle run query logic\n const handleRunQuery = useCallback(async () => {\n // Clear selected table when running a query\n handleSelectTable(undefined);\n\n // Get the query text (either selected text or the entire query)\n const queryToRun = getQueryText(selectedQueryId, currentQuery);\n\n // Store the query that's being executed\n setLastExecutedQuery(queryToRun);\n\n // Run the query and refresh tables list\n await runQuery(queryToRun);\n }, [\n handleSelectTable,\n getQueryText,\n selectedQueryId,\n currentQuery,\n runQuery,\n setLastExecutedQuery,\n ]);\n\n // Set up the run query handler reference for keyboard shortcuts\n useEffect(() => {\n setRunQueryHandler(handleRunQuery);\n }, [handleRunQuery, setRunQueryHandler]);\n\n // Check if table schemas are empty and refetch if needed\n useEffect(() => {\n if (Object.keys(tableSchemas).length === 0) {\n void fetchTables();\n }\n }, [fetchTables, tableSchemas]);\n\n // Handle toggle documentation panel\n const handleToggleDocs = useCallback(() => {\n setShowDocs(!showDocs);\n }, [showDocs]);\n\n // Handle create table from query results\n const handleCreateTable = useCallback(() => {\n setCreateTableModalOpen(true);\n }, []);\n\n return (\n <div className=\"relative flex h-full w-full flex-col overflow-hidden\">\n <div className=\"absolute right-12 top-0\">\n {documentationPanel ? (\n <Button\n size=\"sm\"\n variant={showDocs ? 'secondary' : 'outline'}\n onClick={handleToggleDocs}\n >\n <BookOpenIcon className=\"mr-2 h-4 w-4\" />\n SQL reference\n </Button>\n ) : (\n <a\n href=\"https://duckdb.org/docs/sql/introduction\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n <Button size=\"sm\" variant={'outline'}>\n <BookOpenIcon className=\"mr-2 h-4 w-4\" />\n SQL reference\n </Button>\n </a>\n )}\n </div>\n <div className=\"flex h-full w-full flex-col gap-2\">\n <div className=\"mb-2 ml-1 mr-10 flex items-center gap-2\">\n <h2 className=\"text-lg font-semibold\">SQL Editor</h2>\n </div>\n <div className=\"bg-muted h-full flex-grow\">\n <ResizablePanelGroup direction=\"horizontal\" className=\"h-full\">\n {/* Main panel - takes full width when docs not shown, or 70% when docs shown */}\n <ResizablePanel defaultSize={showDocs ? 70 : 100}>\n <ResizablePanelGroup direction=\"vertical\" className=\"h-full\">\n <ResizablePanel defaultSize={50} className=\"flex flex-row\">\n <ResizablePanelGroup direction=\"horizontal\">\n <ResizablePanel defaultSize={20}>\n {tablesLoading ? (\n <SpinnerPane h=\"100%\" />\n ) : tablesError ? (\n <div className=\"p-4 text-red-500\">\n Error loading tables: {tablesError.message}\n </div>\n ) : (\n <TablesList\n schema=\"information_schema\"\n tableNames={tables}\n selectedTable={selectedTable}\n onSelect={handleSelectTable}\n />\n )}\n </ResizablePanel>\n <ResizableHandle withHandle />\n <ResizablePanel\n defaultSize={80}\n className=\"flex flex-col overflow-hidden\"\n >\n <Tabs\n value={selectedQueryId}\n onValueChange={handleTabChange}\n className=\"flex h-full flex-col overflow-hidden\"\n >\n <div className=\"border-border flex items-center gap-2 border-b\">\n <Button\n size=\"sm\"\n onClick={() => void handleRunQuery()}\n className=\"uppercase\"\n >\n <PlayIcon className=\"mr-2 h-4 w-4\" />\n Run\n </Button>\n <TabsList className=\"flex-1\">\n {queries.map((q: any) => (\n <div key={q.id} className=\"relative\">\n <TabsTrigger\n value={q.id}\n className=\"min-w-[60px] px-6 pr-8\"\n >\n {q.name}\n </TabsTrigger>\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <div\n className=\"hover:bg-accent absolute right-0 top-1/2 flex h-6 w-6 -translate-y-1/2 cursor-pointer items-center justify-center rounded-sm\"\n onClick={(e) => e.stopPropagation()}\n >\n <MoreVerticalIcon className=\"h-3 w-3\" />\n </div>\n </DropdownMenuTrigger>\n <DropdownMenuContent>\n <DropdownMenuItem\n onClick={(e) => {\n e.stopPropagation();\n handleStartRename(q.id, q.name, e);\n }}\n >\n Rename\n </DropdownMenuItem>\n {queries.length > 1 && (\n <DropdownMenuItem\n onClick={(e) => {\n e.stopPropagation();\n handleDeleteQuery(q.id, e);\n }}\n className=\"text-red-500\"\n >\n Delete\n </DropdownMenuItem>\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n ))}\n </TabsList>\n <Button\n size=\"icon\"\n variant=\"ghost\"\n onClick={handleNewQuery}\n className=\"ml-2\"\n >\n <PlusIcon className=\"h-4 w-4\" />\n </Button>\n </div>\n {queries.map((q: any) => (\n <TabsContent\n key={q.id}\n value={q.id}\n className=\"relative h-full flex-grow flex-col data-[state=active]:flex\"\n >\n <div className=\"absolute inset-0 h-full w-full flex-grow\">\n <SqlMonacoEditor\n value={q.query}\n onChange={handleUpdateQuery}\n className=\"h-full w-full flex-grow\"\n options={{\n scrollBeyondLastLine: false,\n automaticLayout: true,\n minimap: {enabled: false},\n wordWrap: 'on',\n // Enable keyboard shortcuts\n quickSuggestions: true,\n suggestOnTriggerCharacters: true,\n }}\n onMount={(\n editor: EditorInstance,\n monaco: MonacoInstance,\n ) => {\n handleEditorMount(\n editor,\n monaco,\n q.id,\n handleRunQuery,\n );\n }}\n tableSchemas={tableSchemas}\n getLatestSchemas={() => {\n // If tableSchemas is empty, try to fetch tables\n if (Object.keys(tableSchemas).length === 0) {\n // We can't await here, but we can trigger the fetch\n // This will update the state for next time\n void fetchTables();\n }\n return {tableSchemas};\n }}\n />\n </div>\n </TabsContent>\n ))}\n </Tabs>\n </ResizablePanel>\n </ResizablePanelGroup>\n </ResizablePanel>\n <ResizableHandle withHandle />\n <ResizablePanel\n defaultSize={50}\n className=\"bg-muted overflow-hidden text-sm\"\n >\n {loading ? (\n <SpinnerPane h=\"100%\" />\n ) : selectedTable ? (\n <QueryDataTable\n query={`SELECT * FROM ${schema}.${escapeId(selectedTable)}`}\n />\n ) : error ? (\n <div className=\"h-full w-full overflow-auto p-5\">\n <pre className=\"text-xs leading-tight text-red-500\">\n {error}\n </pre>\n </div>\n ) : resultsTableData ? (\n <div className=\"relative flex h-full w-full flex-grow flex-col overflow-hidden\">\n <DataTableVirtualized {...resultsTableData} />\n <div className=\"absolute bottom-0 right-0 flex gap-2\">\n <Button\n size=\"sm\"\n disabled={!resultsTableData}\n onClick={handleCreateTable}\n >\n <PlusIcon className=\"mr-2 h-4 w-4\" />\n Create table\n </Button>\n <Button\n size=\"sm\"\n disabled={!results}\n onClick={exportResults}\n >\n <DownloadIcon className=\"mr-2 h-4 w-4\" />\n Export\n </Button>\n </div>\n </div>\n ) : null}\n </ResizablePanel>\n </ResizablePanelGroup>\n </ResizablePanel>\n {showDocs && (\n <>\n <ResizableHandle withHandle />\n {/* Documentation panel - 30% width */}\n <ResizablePanel defaultSize={30}>\n {documentationPanel}\n </ResizablePanel>\n </>\n )}\n </ResizablePanelGroup>\n </div>\n <CreateTableModal\n query={lastExecutedQuery || currentQuery}\n isOpen={createTableModalOpen}\n onClose={() => setCreateTableModalOpen(false)}\n onAddOrUpdateSqlQuery={addOrUpdateSqlQueryDataSource}\n />\n <DeleteSqlQueryModal\n isOpen={queryToDelete !== null}\n onClose={() => setQueryToDelete(null)}\n onConfirm={handleConfirmDeleteQuery}\n />\n <RenameSqlQueryModal\n isOpen={queryToRename !== null}\n onClose={() => setQueryToRename(null)}\n initialName={queryToRename?.name ?? ''}\n onRename={handleFinishRename}\n />\n </div>\n </div>\n );\n};\n\n// Wrap with React.memo to prevent unnecessary re-renders\nconst SqlEditor = React.memo(SqlEditorBase);\n\nexport default SqlEditor;\n"]}
|
package/dist/SqlEditorModal.js
CHANGED
|
@@ -39,7 +39,7 @@ const SqlEditorModal = (props) => {
|
|
|
39
39
|
if (!open)
|
|
40
40
|
onClose();
|
|
41
41
|
}, [onClose]);
|
|
42
|
-
return (_jsxs(Dialog, { open: isOpen, onOpenChange: handleOpenChange, children: [_jsx(DialogOverlay, { className: "bg-background/80" }), _jsxs(DialogContent, { className: "
|
|
42
|
+
return (_jsxs(Dialog, { open: isOpen, onOpenChange: handleOpenChange, children: [_jsx(DialogOverlay, { className: "bg-background/80" }), _jsxs(DialogContent, { className: "h-[100vh] max-h-[100vh] w-[100vw] max-w-[100vw] p-3", children: [_jsxs(DialogHeader, { className: "sr-only", children: [_jsx(DialogTitle, { children: "SQL Editor" }), _jsx(DialogDescription, { children: "SQL editor for querying and managing database tables" })] }), _jsx(Suspense, { fallback: _jsx(SpinnerPane, { h: "100%" }), children: _jsx(SqlEditor, { ...props }) })] })] }));
|
|
43
43
|
};
|
|
44
44
|
export default SqlEditorModal;
|
|
45
45
|
//# sourceMappingURL=SqlEditorModal.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SqlEditorModal.js","sourceRoot":"","sources":["../src/SqlEditorModal.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EACL,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,WAAW,EACX,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,OAAc,EAAC,QAAQ,EAAE,WAAW,EAAC,MAAM,OAAO,CAAC;AACnD,OAAO,SAA2B,MAAM,aAAa,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,cAAc,GAA6B,CAAC,KAAK,EAAE,EAAE;IACzD,MAAM,EAAC,MAAM,EAAE,OAAO,EAAC,GAAG,KAAK,CAAC;IAEhC,4CAA4C;IAC5C,MAAM,gBAAgB,GAAG,WAAW,CAClC,CAAC,IAAa,EAAE,EAAE;QAChB,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,CAAC;IACvB,CAAC,EACD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO,CACL,MAAC,MAAM,IAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,gBAAgB,aAClD,KAAC,aAAa,IAAC,SAAS,EAAC,kBAAkB,GAAG,EAC9C,MAAC,aAAa,IAAC,SAAS,EAAC,qDAAqD,aAC5E,MAAC,YAAY,IAAC,SAAS,EAAC,SAAS,aAC/B,KAAC,WAAW,6BAAyB,EACrC,KAAC,iBAAiB,uEAEE,IACP,EACf,KAAC,QAAQ,IAAC,QAAQ,EAAE,KAAC,WAAW,IAAC,CAAC,EAAC,MAAM,GAAG,YAC1C,KAAC,SAAS,OAAK,KAAK,GAAI,GACf,IACG,IACT,CACV,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,cAAc,CAAC","sourcesContent":["'use client';\n\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogOverlay,\n DialogTitle,\n SpinnerPane,\n} from '@sqlrooms/ui';\nimport React, {Suspense, useCallback} from 'react';\nimport SqlEditor, {SqlEditorProps} from './SqlEditor';\n\n/**\n * A modal wrapper for the SQL Editor component that provides a full-screen dialog interface.\n *\n * This component wraps the main SqlEditor component in a modal dialog, making it suitable for\n * overlay/popup usage scenarios. It inherits all props from SqlEditorProps and handles the\n * modal-specific behavior.\n *\n * @example\n * ```tsx\n * <SqlEditorModal\n * isOpen={true}\n * onClose={() => setIsOpen(false)}\n * sqlEditorConfig={config}\n * onChange={handleConfigChange}\n * />\n * ```\n *\n * @see {@link SqlEditor} for detailed documentation of all available props\n *\n * @props {@link SqlEditorProps}\n * The component accepts all props from SqlEditorProps:\n * - `isOpen` - Whether the SQL editor modal is currently visible\n * - `onClose` - Callback fired when the modal should be closed\n * - `sqlEditorConfig` - Configuration object containing queries and selected query state\n * - `onChange` - Callback fired when the SQL editor configuration changes\n * - `schema` - Optional database schema to use for queries (defaults to 'main')\n * - `documentationPanel` - Optional component to render SQL documentation in the side panel\n * - `onAddOrUpdateSqlQuery` - Callback fired when a new table should be created from query results\n */\nconst SqlEditorModal: React.FC<SqlEditorProps> = (props) => {\n const {isOpen, onClose} = props;\n\n // Memoize the handler to prevent re-renders\n const handleOpenChange = useCallback(\n (open: boolean) => {\n if (!open) onClose();\n },\n [onClose],\n );\n\n return (\n <Dialog open={isOpen} onOpenChange={handleOpenChange}>\n <DialogOverlay className=\"bg-background/80\" />\n <DialogContent className=\"
|
|
1
|
+
{"version":3,"file":"SqlEditorModal.js","sourceRoot":"","sources":["../src/SqlEditorModal.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EACL,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,WAAW,EACX,WAAW,GACZ,MAAM,cAAc,CAAC;AACtB,OAAc,EAAC,QAAQ,EAAE,WAAW,EAAC,MAAM,OAAO,CAAC;AACnD,OAAO,SAA2B,MAAM,aAAa,CAAC;AAEtD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,cAAc,GAA6B,CAAC,KAAK,EAAE,EAAE;IACzD,MAAM,EAAC,MAAM,EAAE,OAAO,EAAC,GAAG,KAAK,CAAC;IAEhC,4CAA4C;IAC5C,MAAM,gBAAgB,GAAG,WAAW,CAClC,CAAC,IAAa,EAAE,EAAE;QAChB,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,CAAC;IACvB,CAAC,EACD,CAAC,OAAO,CAAC,CACV,CAAC;IAEF,OAAO,CACL,MAAC,MAAM,IAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,gBAAgB,aAClD,KAAC,aAAa,IAAC,SAAS,EAAC,kBAAkB,GAAG,EAC9C,MAAC,aAAa,IAAC,SAAS,EAAC,qDAAqD,aAC5E,MAAC,YAAY,IAAC,SAAS,EAAC,SAAS,aAC/B,KAAC,WAAW,6BAAyB,EACrC,KAAC,iBAAiB,uEAEE,IACP,EACf,KAAC,QAAQ,IAAC,QAAQ,EAAE,KAAC,WAAW,IAAC,CAAC,EAAC,MAAM,GAAG,YAC1C,KAAC,SAAS,OAAK,KAAK,GAAI,GACf,IACG,IACT,CACV,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,cAAc,CAAC","sourcesContent":["'use client';\n\nimport {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogHeader,\n DialogOverlay,\n DialogTitle,\n SpinnerPane,\n} from '@sqlrooms/ui';\nimport React, {Suspense, useCallback} from 'react';\nimport SqlEditor, {SqlEditorProps} from './SqlEditor';\n\n/**\n * A modal wrapper for the SQL Editor component that provides a full-screen dialog interface.\n *\n * This component wraps the main SqlEditor component in a modal dialog, making it suitable for\n * overlay/popup usage scenarios. It inherits all props from SqlEditorProps and handles the\n * modal-specific behavior.\n *\n * @example\n * ```tsx\n * <SqlEditorModal\n * isOpen={true}\n * onClose={() => setIsOpen(false)}\n * sqlEditorConfig={config}\n * onChange={handleConfigChange}\n * />\n * ```\n *\n * @see {@link SqlEditor} for detailed documentation of all available props\n *\n * @props {@link SqlEditorProps}\n * The component accepts all props from SqlEditorProps:\n * - `isOpen` - Whether the SQL editor modal is currently visible\n * - `onClose` - Callback fired when the modal should be closed\n * - `sqlEditorConfig` - Configuration object containing queries and selected query state\n * - `onChange` - Callback fired when the SQL editor configuration changes\n * - `schema` - Optional database schema to use for queries (defaults to 'main')\n * - `documentationPanel` - Optional component to render SQL documentation in the side panel\n * - `onAddOrUpdateSqlQuery` - Callback fired when a new table should be created from query results\n */\nconst SqlEditorModal: React.FC<SqlEditorProps> = (props) => {\n const {isOpen, onClose} = props;\n\n // Memoize the handler to prevent re-renders\n const handleOpenChange = useCallback(\n (open: boolean) => {\n if (!open) onClose();\n },\n [onClose],\n );\n\n return (\n <Dialog open={isOpen} onOpenChange={handleOpenChange}>\n <DialogOverlay className=\"bg-background/80\" />\n <DialogContent className=\"h-[100vh] max-h-[100vh] w-[100vw] max-w-[100vw] p-3\">\n <DialogHeader className=\"sr-only\">\n <DialogTitle>SQL Editor</DialogTitle>\n <DialogDescription>\n SQL editor for querying and managing database tables\n </DialogDescription>\n </DialogHeader>\n <Suspense fallback={<SpinnerPane h=\"100%\" />}>\n <SqlEditor {...props} />\n </Suspense>\n </DialogContent>\n </Dialog>\n );\n};\n\nexport default SqlEditorModal;\n"]}
|