@sqlrooms/sql-editor 0.15.0 → 0.16.0

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.
Files changed (93) hide show
  1. package/README.md +3 -4
  2. package/dist/SqlEditor.d.ts.map +1 -1
  3. package/dist/SqlEditor.js +22 -136
  4. package/dist/SqlEditor.js.map +1 -1
  5. package/dist/SqlEditorSlice.d.ts +58 -15
  6. package/dist/SqlEditorSlice.d.ts.map +1 -1
  7. package/dist/SqlEditorSlice.js +244 -94
  8. package/dist/SqlEditorSlice.js.map +1 -1
  9. package/dist/SqlMonacoEditor.d.ts.map +1 -1
  10. package/dist/SqlMonacoEditor.js +2 -1
  11. package/dist/SqlMonacoEditor.js.map +1 -1
  12. package/dist/components/CreateTableModal.d.ts.map +1 -0
  13. package/dist/{CreateTableModal.js → components/CreateTableModal.js} +2 -10
  14. package/dist/components/CreateTableModal.js.map +1 -0
  15. package/dist/components/DeleteSqlQueryModal.d.ts.map +1 -0
  16. package/dist/components/DeleteSqlQueryModal.js.map +1 -0
  17. package/dist/components/QueryEditorPanel.d.ts +9 -0
  18. package/dist/components/QueryEditorPanel.d.ts.map +1 -0
  19. package/dist/components/QueryEditorPanel.js +14 -0
  20. package/dist/components/QueryEditorPanel.js.map +1 -0
  21. package/dist/components/QueryEditorPanelActions.d.ts +5 -0
  22. package/dist/components/QueryEditorPanelActions.d.ts.map +1 -0
  23. package/dist/components/QueryEditorPanelActions.js +53 -0
  24. package/dist/components/QueryEditorPanelActions.js.map +1 -0
  25. package/dist/components/QueryEditorPanelEditor.d.ts +5 -0
  26. package/dist/components/QueryEditorPanelEditor.d.ts.map +1 -0
  27. package/dist/components/QueryEditorPanelEditor.js +45 -0
  28. package/dist/components/QueryEditorPanelEditor.js.map +1 -0
  29. package/dist/components/QueryEditorPanelTabsList.d.ts +5 -0
  30. package/dist/components/QueryEditorPanelTabsList.d.ts.map +1 -0
  31. package/dist/components/QueryEditorPanelTabsList.js +71 -0
  32. package/dist/components/QueryEditorPanelTabsList.js.map +1 -0
  33. package/dist/components/QueryResultPanel.d.ts +12 -0
  34. package/dist/components/QueryResultPanel.d.ts.map +1 -0
  35. package/dist/components/QueryResultPanel.js +30 -0
  36. package/dist/components/QueryResultPanel.js.map +1 -0
  37. package/dist/components/RenameSqlQueryModal.d.ts.map +1 -0
  38. package/dist/components/RenameSqlQueryModal.js +29 -0
  39. package/dist/components/RenameSqlQueryModal.js.map +1 -0
  40. package/dist/components/SqlEditorHeader.d.ts +15 -0
  41. package/dist/components/SqlEditorHeader.d.ts.map +1 -0
  42. package/dist/components/SqlEditorHeader.js +7 -0
  43. package/dist/components/SqlEditorHeader.js.map +1 -0
  44. package/dist/components/SqlQueryDataSourcesPanel.d.ts.map +1 -0
  45. package/dist/components/SqlQueryDataSourcesPanel.js.map +1 -0
  46. package/dist/components/SqlReferenceButton.d.ts +12 -0
  47. package/dist/components/SqlReferenceButton.d.ts.map +1 -0
  48. package/dist/components/SqlReferenceButton.js +10 -0
  49. package/dist/components/SqlReferenceButton.js.map +1 -0
  50. package/dist/components/TableStructurePanel.d.ts +13 -0
  51. package/dist/components/TableStructurePanel.d.ts.map +1 -0
  52. package/dist/components/TableStructurePanel.js +21 -0
  53. package/dist/components/TableStructurePanel.js.map +1 -0
  54. package/dist/index.d.ts +10 -2
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +10 -2
  57. package/dist/index.js.map +1 -1
  58. package/package.json +17 -16
  59. package/dist/CreateTableModal.d.ts.map +0 -1
  60. package/dist/CreateTableModal.js.map +0 -1
  61. package/dist/DeleteSqlQueryModal.d.ts.map +0 -1
  62. package/dist/DeleteSqlQueryModal.js.map +0 -1
  63. package/dist/RenameSqlQueryModal.d.ts.map +0 -1
  64. package/dist/RenameSqlQueryModal.js +0 -27
  65. package/dist/RenameSqlQueryModal.js.map +0 -1
  66. package/dist/SqlQueryDataSourcesPanel.d.ts.map +0 -1
  67. package/dist/SqlQueryDataSourcesPanel.js.map +0 -1
  68. package/dist/hooks/index.d.ts +0 -5
  69. package/dist/hooks/index.d.ts.map +0 -1
  70. package/dist/hooks/index.js +0 -5
  71. package/dist/hooks/index.js.map +0 -1
  72. package/dist/hooks/useMonacoEditor.d.ts +0 -13
  73. package/dist/hooks/useMonacoEditor.d.ts.map +0 -1
  74. package/dist/hooks/useMonacoEditor.js +0 -78
  75. package/dist/hooks/useMonacoEditor.js.map +0 -1
  76. package/dist/hooks/useQueryExecution.d.ts +0 -17
  77. package/dist/hooks/useQueryExecution.d.ts.map +0 -1
  78. package/dist/hooks/useQueryExecution.js +0 -61
  79. package/dist/hooks/useQueryExecution.js.map +0 -1
  80. package/dist/hooks/useQueryTabManagement.d.ts +0 -41
  81. package/dist/hooks/useQueryTabManagement.d.ts.map +0 -1
  82. package/dist/hooks/useQueryTabManagement.js +0 -95
  83. package/dist/hooks/useQueryTabManagement.js.map +0 -1
  84. package/dist/hooks/useTableManagement.d.ts +0 -14
  85. package/dist/hooks/useTableManagement.d.ts.map +0 -1
  86. package/dist/hooks/useTableManagement.js +0 -46
  87. package/dist/hooks/useTableManagement.js.map +0 -1
  88. /package/dist/{CreateTableModal.d.ts → components/CreateTableModal.d.ts} +0 -0
  89. /package/dist/{DeleteSqlQueryModal.d.ts → components/DeleteSqlQueryModal.d.ts} +0 -0
  90. /package/dist/{DeleteSqlQueryModal.js → components/DeleteSqlQueryModal.js} +0 -0
  91. /package/dist/{RenameSqlQueryModal.d.ts → components/RenameSqlQueryModal.d.ts} +0 -0
  92. /package/dist/{SqlQueryDataSourcesPanel.d.ts → components/SqlQueryDataSourcesPanel.d.ts} +0 -0
  93. /package/dist/{SqlQueryDataSourcesPanel.js → components/SqlQueryDataSourcesPanel.js} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CreateTableModal.js","sourceRoot":"","sources":["../../src/components/CreateTableModal.tsx"],"names":[],"mappings":"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","sourcesContent":["import {zodResolver} from '@hookform/resolvers/zod';\nimport {SqlQueryDataSource} from '@sqlrooms/project-builder';\nimport {\n Alert,\n AlertDescription,\n Button,\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n} from '@sqlrooms/ui';\nimport {FC, useCallback} from 'react';\nimport {useForm} from 'react-hook-form';\nimport * as z from 'zod';\nimport {SqlMonacoEditor} from '../SqlMonacoEditor';\n\nconst VALID_TABLE_OR_COLUMN_REGEX = /^[a-zA-Z_][a-zA-Z0-9_]{0,62}$/;\n\nconst formSchema = z.object({\n tableName: z\n .string()\n .min(1, 'Table name is required')\n .regex(\n VALID_TABLE_OR_COLUMN_REGEX,\n 'Only letters, digits and underscores are allowed; should not start with a digit',\n ),\n query: z.string().min(1, 'Query is required'),\n});\n\nexport type CreateTableModalProps = {\n query: string;\n isOpen: boolean;\n onClose: () => void;\n editDataSource?: SqlQueryDataSource;\n onAddOrUpdateSqlQuery: (\n tableName: string,\n query: string,\n oldTableName?: string,\n ) => Promise<void>;\n};\n\nconst CreateTableModal: FC<CreateTableModalProps> = (props) => {\n const {editDataSource, isOpen, onClose, onAddOrUpdateSqlQuery} = props;\n\n const form = useForm<z.infer<typeof formSchema>>({\n resolver: zodResolver(formSchema),\n values: {\n tableName: editDataSource?.tableName ?? '',\n query: editDataSource?.sqlQuery ?? props.query.trim(),\n },\n });\n\n const onSubmit = useCallback(\n async (values: z.infer<typeof formSchema>) => {\n try {\n const {tableName, query} = values;\n await onAddOrUpdateSqlQuery(\n tableName,\n query,\n editDataSource?.tableName,\n );\n form.reset();\n onClose();\n } catch (err) {\n form.setError('root', {type: 'manual', message: `${err}`});\n }\n },\n [onAddOrUpdateSqlQuery, editDataSource?.tableName, onClose, form],\n );\n\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>\n <DialogContent className=\"sm:max-w-[800px]\">\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)} className=\"space-y-4\">\n <DialogHeader>\n <DialogTitle>\n {editDataSource\n ? 'Edit table query'\n : 'Create table from query'}\n </DialogTitle>\n {!editDataSource && (\n <DialogDescription>\n Create a new table from the results of an SQL query.\n </DialogDescription>\n )}\n </DialogHeader>\n\n {form.formState.errors.root && (\n <Alert variant=\"destructive\">\n <AlertDescription className=\"whitespace-pre-wrap font-mono text-xs\">\n {form.formState.errors.root.message}\n </AlertDescription>\n </Alert>\n )}\n\n <FormField\n control={form.control}\n name=\"tableName\"\n render={({field}) => (\n <FormItem>\n <FormLabel>Table name:</FormLabel>\n <FormControl>\n <Input {...field} className=\"font-mono\" autoFocus />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n <FormField\n control={form.control}\n name=\"query\"\n render={({field}) => (\n <FormItem className=\"flex flex-col\">\n <FormLabel>SQL query:</FormLabel>\n <FormControl>\n <SqlMonacoEditor\n value={field.value}\n onChange={field.onChange}\n className=\"h-[200px] w-full\"\n options={{\n scrollBeyondLastLine: false,\n automaticLayout: true,\n minimap: {enabled: false},\n wordWrap: 'on',\n }}\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n\n <DialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={onClose}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={form.formState.isSubmitting}>\n {editDataSource ? 'Update' : 'Create'}\n </Button>\n </DialogFooter>\n </form>\n </Form>\n </DialogContent>\n </Dialog>\n );\n};\n\nexport default CreateTableModal;\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeleteSqlQueryModal.d.ts","sourceRoot":"","sources":["../../src/components/DeleteSqlQueryModal.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,QAAA,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,IAAI,CAAC;CACvB,CAsBA,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DeleteSqlQueryModal.js","sourceRoot":"","sources":["../../src/components/DeleteSqlQueryModal.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,MAAM,EACN,aAAa,EACb,iBAAiB,EACjB,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,MAAM,GACP,MAAM,cAAc,CAAC;AAGtB,MAAM,mBAAmB,GAIpB,CAAC,EAAC,MAAM,EAAE,OAAO,EAAE,SAAS,EAAC,EAAE,EAAE;IACpC,OAAO,CACL,KAAC,MAAM,IAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,OAAO,EAAE,YAC9D,MAAC,aAAa,eACZ,MAAC,YAAY,eACX,KAAC,WAAW,+BAA2B,EACvC,KAAC,iBAAiB,4FAGE,IACP,EACf,MAAC,YAAY,eACX,KAAC,MAAM,IAAC,OAAO,EAAC,SAAS,EAAC,OAAO,EAAE,OAAO,uBAEjC,EACT,KAAC,MAAM,IAAC,OAAO,EAAC,aAAa,EAAC,OAAO,EAAE,SAAS,uBAEvC,IACI,IACD,GACT,CACV,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,mBAAmB,CAAC","sourcesContent":["import {\n Dialog,\n DialogContent,\n DialogDescription,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Button,\n} from '@sqlrooms/ui';\nimport React from 'react';\n\nconst DeleteSqlQueryModal: React.FC<{\n isOpen: boolean;\n onClose: () => void;\n onConfirm: () => void;\n}> = ({isOpen, onClose, onConfirm}) => {\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Delete Query</DialogTitle>\n <DialogDescription>\n Are you sure you want to delete this query? This action cannot be\n undone.\n </DialogDescription>\n </DialogHeader>\n <DialogFooter>\n <Button variant=\"outline\" onClick={onClose}>\n Cancel\n </Button>\n <Button variant=\"destructive\" onClick={onConfirm}>\n Delete\n </Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n );\n};\n\nexport default DeleteSqlQueryModal;\n"]}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ export interface QueryEditorPanelProps {
3
+ /** Custom class name for styling */
4
+ className?: string;
5
+ /** The database schema to use. Defaults to 'main' */
6
+ schema?: string;
7
+ }
8
+ export declare const QueryEditorPanel: React.FC<QueryEditorPanelProps>;
9
+ //# sourceMappingURL=QueryEditorPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueryEditorPanel.d.ts","sourceRoot":"","sources":["../../src/components/QueryEditorPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAO1B,MAAM,WAAW,qBAAqB;IACpC,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAsC5D,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn, Tabs, TabsContent } from '@sqlrooms/ui';
3
+ import { useStoreWithSqlEditor } from '../SqlEditorSlice';
4
+ import { QueryEditorPanelActions } from './QueryEditorPanelActions';
5
+ import { QueryEditorPanelEditor } from './QueryEditorPanelEditor';
6
+ import { QueryEditorPanelTabsList } from './QueryEditorPanelTabsList';
7
+ export const QueryEditorPanel = ({ className, }) => {
8
+ // Get state and actions from store in a single call
9
+ const selectedQueryId = useStoreWithSqlEditor((s) => s.config.sqlEditor.selectedQueryId);
10
+ const queries = useStoreWithSqlEditor((s) => s.config.sqlEditor.queries);
11
+ const setSelectedQueryId = useStoreWithSqlEditor((s) => s.sqlEditor.setSelectedQueryId);
12
+ return (_jsxs(Tabs, { value: selectedQueryId, onValueChange: setSelectedQueryId, className: cn('flex h-full flex-col overflow-hidden', className), children: [_jsxs("div", { className: "border-border flex items-center border-b p-1", children: [_jsx(QueryEditorPanelActions, {}), _jsx(QueryEditorPanelTabsList, {})] }), 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: q.id === selectedQueryId && (_jsx(QueryEditorPanelEditor, { queryId: q.id })) }) }, q.id)))] }));
13
+ };
14
+ //# sourceMappingURL=QueryEditorPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueryEditorPanel.js","sourceRoot":"","sources":["../../src/components/QueryEditorPanel.tsx"],"names":[],"mappings":";AACA,OAAO,EAAC,EAAE,EAAE,IAAI,EAAE,WAAW,EAAC,MAAM,cAAc,CAAC;AACnD,OAAO,EAAC,qBAAqB,EAAC,MAAM,mBAAmB,CAAC;AACxD,OAAO,EAAC,uBAAuB,EAAC,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAC,sBAAsB,EAAC,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAC,wBAAwB,EAAC,MAAM,4BAA4B,CAAC;AASpE,MAAM,CAAC,MAAM,gBAAgB,GAAoC,CAAC,EAChE,SAAS,GACV,EAAE,EAAE;IACH,oDAAoD;IAEpD,MAAM,eAAe,GAAG,qBAAqB,CAC3C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAC1C,CAAC;IACF,MAAM,OAAO,GAAG,qBAAqB,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACzE,MAAM,kBAAkB,GAAG,qBAAqB,CAC9C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,kBAAkB,CACtC,CAAC;IAEF,OAAO,CACL,MAAC,IAAI,IACH,KAAK,EAAE,eAAe,EACtB,aAAa,EAAE,kBAAkB,EACjC,SAAS,EAAE,EAAE,CAAC,sCAAsC,EAAE,SAAS,CAAC,aAEhE,eAAK,SAAS,EAAC,8CAA8C,aAC3D,KAAC,uBAAuB,KAAG,EAC3B,KAAC,wBAAwB,KAAG,IACxB,EACL,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAClB,KAAC,WAAW,IAEV,KAAK,EAAE,CAAC,CAAC,EAAE,EACX,SAAS,EAAC,6DAA6D,YAEvE,cAAK,SAAS,EAAC,0CAA0C,YACtD,CAAC,CAAC,EAAE,KAAK,eAAe,IAAI,CAC3B,KAAC,sBAAsB,IAAC,OAAO,EAAE,CAAC,CAAC,EAAE,GAAI,CAC1C,GACG,IARD,CAAC,CAAC,EAAE,CASG,CACf,CAAC,IACG,CACR,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import React from 'react';\nimport {cn, Tabs, TabsContent} from '@sqlrooms/ui';\nimport {useStoreWithSqlEditor} from '../SqlEditorSlice';\nimport {QueryEditorPanelActions} from './QueryEditorPanelActions';\nimport {QueryEditorPanelEditor} from './QueryEditorPanelEditor';\nimport {QueryEditorPanelTabsList} from './QueryEditorPanelTabsList';\n\nexport interface QueryEditorPanelProps {\n /** Custom class name for styling */\n className?: string;\n /** The database schema to use. Defaults to 'main' */\n schema?: string;\n}\n\nexport const QueryEditorPanel: React.FC<QueryEditorPanelProps> = ({\n className,\n}) => {\n // Get state and actions from store in a single call\n\n const selectedQueryId = useStoreWithSqlEditor(\n (s) => s.config.sqlEditor.selectedQueryId,\n );\n const queries = useStoreWithSqlEditor((s) => s.config.sqlEditor.queries);\n const setSelectedQueryId = useStoreWithSqlEditor(\n (s) => s.sqlEditor.setSelectedQueryId,\n );\n\n return (\n <Tabs\n value={selectedQueryId}\n onValueChange={setSelectedQueryId}\n className={cn('flex h-full flex-col overflow-hidden', className)}\n >\n <div className=\"border-border flex items-center border-b p-1\">\n <QueryEditorPanelActions />\n <QueryEditorPanelTabsList />\n </div>\n {queries.map((q) => (\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 {q.id === selectedQueryId && (\n <QueryEditorPanelEditor queryId={q.id} />\n )}\n </div>\n </TabsContent>\n ))}\n </Tabs>\n );\n};\n"]}
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ export declare const QueryEditorPanelActions: React.FC<{
3
+ className?: string;
4
+ }>;
5
+ //# sourceMappingURL=QueryEditorPanelActions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueryEditorPanelActions.d.ts","sourceRoot":"","sources":["../../src/components/QueryEditorPanelActions.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,eAAO,MAAM,uBAAuB,EAAE,KAAK,CAAC,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAC,CA+ElE,CAAC"}
@@ -0,0 +1,53 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, cn, Tooltip, TooltipContent, TooltipTrigger, } from '@sqlrooms/ui';
3
+ import { isMacOS } from '@sqlrooms/utils';
4
+ import { Loader2, OctagonXIcon, PlayIcon } from 'lucide-react';
5
+ import { useStoreWithSqlEditor } from '../SqlEditorSlice';
6
+ export const QueryEditorPanelActions = ({ className, }) => {
7
+ const runCurrentQuery = useStoreWithSqlEditor((s) => s.sqlEditor.parseAndRunCurrentQuery);
8
+ const abortCurrentQuery = useStoreWithSqlEditor((s) => s.sqlEditor.abortCurrentQuery);
9
+ const queryResult = useStoreWithSqlEditor((s) => s.sqlEditor.queryResult);
10
+ const isMac = isMacOS();
11
+ const isLoading = queryResult?.status === 'loading';
12
+ const isAborted = queryResult?.status === 'loading' && queryResult.isBeingAborted;
13
+ const handleClick = () => {
14
+ if (isLoading) {
15
+ abortCurrentQuery();
16
+ }
17
+ else {
18
+ runCurrentQuery();
19
+ }
20
+ };
21
+ const getButtonContent = () => {
22
+ if (isLoading) {
23
+ if (isAborted) {
24
+ return {
25
+ icon: _jsx(Loader2, { className: "h-3 w-3 animate-spin" }),
26
+ text: 'Cancelling...',
27
+ disabled: true,
28
+ };
29
+ }
30
+ else {
31
+ return {
32
+ icon: _jsx(Loader2, { className: "h-3 w-3 animate-spin" }),
33
+ text: 'Cancel',
34
+ disabled: false,
35
+ rightIcon: _jsx(OctagonXIcon, { className: "h-3 w-3" }),
36
+ };
37
+ }
38
+ }
39
+ else {
40
+ return {
41
+ icon: _jsx(PlayIcon, { className: "h-3 w-3" }),
42
+ text: 'Run',
43
+ disabled: false,
44
+ rightIcon: _jsx("span", { children: isMac ? '⌘↵' : '⌃↵' }),
45
+ };
46
+ }
47
+ };
48
+ const buttonContent = getButtonContent();
49
+ return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs(Button, { className: cn('flex w-[110px] items-center gap-2', className), variant: 'outline', size: "xs", onClick: handleClick, disabled: buttonContent.disabled, children: [buttonContent.icon, _jsx("span", { children: buttonContent.text }), buttonContent.rightIcon] }) }), _jsx(TooltipContent, { children: isLoading
50
+ ? 'Cancel the running query'
51
+ : `Use ${isMac ? 'Cmd' : 'Ctrl'}+Enter to run query or selected text` })] }));
52
+ };
53
+ //# sourceMappingURL=QueryEditorPanelActions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueryEditorPanelActions.js","sourceRoot":"","sources":["../../src/components/QueryEditorPanelActions.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n Button,\n cn,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '@sqlrooms/ui';\nimport {isMacOS} from '@sqlrooms/utils';\nimport {Loader2, OctagonXIcon, PlayIcon} from 'lucide-react';\nimport React from 'react';\nimport {useStoreWithSqlEditor} from '../SqlEditorSlice';\n\nexport const QueryEditorPanelActions: React.FC<{className?: string}> = ({\n className,\n}) => {\n const runCurrentQuery = useStoreWithSqlEditor(\n (s) => s.sqlEditor.parseAndRunCurrentQuery,\n );\n const abortCurrentQuery = useStoreWithSqlEditor(\n (s) => s.sqlEditor.abortCurrentQuery,\n );\n const queryResult = useStoreWithSqlEditor((s) => s.sqlEditor.queryResult);\n const isMac = isMacOS();\n\n const isLoading = queryResult?.status === 'loading';\n const isAborted =\n queryResult?.status === 'loading' && queryResult.isBeingAborted;\n\n const handleClick = () => {\n if (isLoading) {\n abortCurrentQuery();\n } else {\n runCurrentQuery();\n }\n };\n\n const getButtonContent = (): {\n icon: React.ReactNode;\n text: string;\n disabled: boolean;\n rightIcon?: React.ReactNode;\n } => {\n if (isLoading) {\n if (isAborted) {\n return {\n icon: <Loader2 className=\"h-3 w-3 animate-spin\" />,\n text: 'Cancelling...',\n disabled: true,\n };\n } else {\n return {\n icon: <Loader2 className=\"h-3 w-3 animate-spin\" />,\n text: 'Cancel',\n disabled: false,\n rightIcon: <OctagonXIcon className=\"h-3 w-3\" />,\n };\n }\n } else {\n return {\n icon: <PlayIcon className=\"h-3 w-3\" />,\n text: 'Run',\n disabled: false,\n rightIcon: <span>{isMac ? '⌘↵' : '⌃↵'}</span>,\n };\n }\n };\n\n const buttonContent = getButtonContent();\n\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n className={cn('flex w-[110px] items-center gap-2', className)}\n variant={'outline'}\n size=\"xs\"\n onClick={handleClick}\n disabled={buttonContent.disabled}\n >\n {buttonContent.icon}\n <span>{buttonContent.text}</span>\n {buttonContent.rightIcon}\n </Button>\n </TooltipTrigger>\n <TooltipContent>\n {isLoading\n ? 'Cancel the running query'\n : `Use ${isMac ? 'Cmd' : 'Ctrl'}+Enter to run query or selected text`}\n </TooltipContent>\n </Tooltip>\n );\n};\n"]}
@@ -0,0 +1,5 @@
1
+ export declare const QueryEditorPanelEditor: React.FC<{
2
+ className?: string;
3
+ queryId: string;
4
+ }>;
5
+ //# sourceMappingURL=QueryEditorPanelEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueryEditorPanelEditor.d.ts","sourceRoot":"","sources":["../../src/components/QueryEditorPanelEditor.tsx"],"names":[],"mappings":"AASA,eAAO,MAAM,sBAAsB,EAAE,KAAK,CAAC,EAAE,CAAC;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB,CA8DA,CAAC"}
@@ -0,0 +1,45 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useRef, useCallback } from 'react';
3
+ import { useStoreWithSqlEditor } from '../SqlEditorSlice';
4
+ import { SqlMonacoEditor } from '../SqlMonacoEditor';
5
+ import { cn } from '@sqlrooms/ui';
6
+ export const QueryEditorPanelEditor = ({ className, queryId }) => {
7
+ const tableSchemas = useStoreWithSqlEditor((s) => s.db.tables);
8
+ const runQuery = useStoreWithSqlEditor((s) => s.sqlEditor.parseAndRunQuery);
9
+ const queryText = useStoreWithSqlEditor((s) => s.config.sqlEditor.queries.find((q) => q.id === queryId)?.query);
10
+ const updateQueryText = useStoreWithSqlEditor((s) => s.sqlEditor.updateQueryText);
11
+ // Editor instance ref for keyboard shortcuts
12
+ const editorRef = useRef({});
13
+ // Handle query text update
14
+ const handleUpdateQuery = useCallback((value) => {
15
+ if (!value)
16
+ return;
17
+ updateQueryText(queryId, value);
18
+ }, [queryId, updateQueryText]);
19
+ // Handle editor mount
20
+ const handleEditorMount = useCallback((editor, monaco, queryId) => {
21
+ editorRef.current[queryId] = editor;
22
+ // Add keyboard shortcut for running query
23
+ editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => {
24
+ const model = editor.getModel();
25
+ const selection = editor.getSelection();
26
+ if (model && selection && !selection.isEmpty()) {
27
+ runQuery(model.getValueInRange(selection));
28
+ }
29
+ else {
30
+ runQuery(editor.getValue());
31
+ }
32
+ });
33
+ }, [runQuery]);
34
+ return (_jsx(SqlMonacoEditor, { value: queryText ?? '', onChange: handleUpdateQuery, className: cn('h-full w-full flex-grow', className), options: {
35
+ scrollBeyondLastLine: false,
36
+ automaticLayout: true,
37
+ minimap: { enabled: false },
38
+ wordWrap: 'on',
39
+ quickSuggestions: true,
40
+ suggestOnTriggerCharacters: true,
41
+ }, onMount: (editor, monaco) => {
42
+ handleEditorMount(editor, monaco, queryId);
43
+ }, tableSchemas: tableSchemas, getLatestSchemas: () => ({ tableSchemas }) }));
44
+ };
45
+ //# sourceMappingURL=QueryEditorPanelEditor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueryEditorPanelEditor.js","sourceRoot":"","sources":["../../src/components/QueryEditorPanelEditor.tsx"],"names":[],"mappings":"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","sourcesContent":["import {useRef, useCallback} from 'react';\nimport {useStoreWithSqlEditor} from '../SqlEditorSlice';\nimport {SqlMonacoEditor} from '../SqlMonacoEditor';\nimport type * as Monaco from 'monaco-editor';\nimport {cn} from '@sqlrooms/ui';\n\ntype EditorInstance = Monaco.editor.IStandaloneCodeEditor;\ntype MonacoInstance = typeof Monaco;\n\nexport const QueryEditorPanelEditor: React.FC<{\n className?: string;\n queryId: string;\n}> = ({className, queryId}) => {\n const tableSchemas = useStoreWithSqlEditor((s) => s.db.tables);\n const runQuery = useStoreWithSqlEditor((s) => s.sqlEditor.parseAndRunQuery);\n\n const queryText = useStoreWithSqlEditor(\n (s) => s.config.sqlEditor.queries.find((q) => q.id === queryId)?.query,\n );\n const updateQueryText = useStoreWithSqlEditor(\n (s) => s.sqlEditor.updateQueryText,\n );\n // Editor instance ref for keyboard shortcuts\n const editorRef = useRef<{\n [key: string]: EditorInstance;\n }>({});\n\n // Handle query text update\n const handleUpdateQuery = useCallback(\n (value: string | undefined) => {\n if (!value) return;\n updateQueryText(queryId, value);\n },\n [queryId, updateQueryText],\n );\n\n // Handle editor mount\n const handleEditorMount = useCallback(\n (editor: EditorInstance, monaco: MonacoInstance, queryId: string) => {\n editorRef.current[queryId] = editor;\n // Add keyboard shortcut for running query\n editor.addCommand(monaco.KeyMod.CtrlCmd | monaco.KeyCode.Enter, () => {\n const model = editor.getModel();\n const selection = editor.getSelection();\n if (model && selection && !selection.isEmpty()) {\n runQuery(model.getValueInRange(selection));\n } else {\n runQuery(editor.getValue());\n }\n });\n },\n [runQuery],\n );\n\n return (\n <SqlMonacoEditor\n value={queryText ?? ''}\n onChange={handleUpdateQuery}\n className={cn('h-full w-full flex-grow', className)}\n options={{\n scrollBeyondLastLine: false,\n automaticLayout: true,\n minimap: {enabled: false},\n wordWrap: 'on',\n quickSuggestions: true,\n suggestOnTriggerCharacters: true,\n }}\n onMount={(editor: EditorInstance, monaco: MonacoInstance) => {\n handleEditorMount(editor, monaco, queryId);\n }}\n tableSchemas={tableSchemas}\n getLatestSchemas={() => ({tableSchemas})}\n />\n );\n};\n"]}
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ export declare const QueryEditorPanelTabsList: React.FC<{
3
+ className?: string;
4
+ }>;
5
+ //# sourceMappingURL=QueryEditorPanelTabsList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueryEditorPanelTabsList.d.ts","sourceRoot":"","sources":["../../src/components/QueryEditorPanelTabsList.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAKzC,eAAO,MAAM,wBAAwB,EAAE,KAAK,CAAC,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAC,CAwKnE,CAAC"}
@@ -0,0 +1,71 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Button, cn, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, EditableText, TabsList, TabsTrigger, } from '@sqlrooms/ui';
3
+ import { MoreVerticalIcon, PlusIcon } from 'lucide-react';
4
+ import React, { useCallback } from 'react';
5
+ import { useStoreWithSqlEditor } from '../SqlEditorSlice';
6
+ import DeleteSqlQueryModal from './DeleteSqlQueryModal';
7
+ import RenameSqlQueryModal from './RenameSqlQueryModal';
8
+ export const QueryEditorPanelTabsList = ({ className, }) => {
9
+ const queries = useStoreWithSqlEditor((s) => s.config.sqlEditor.queries);
10
+ const renameQueryTab = useStoreWithSqlEditor((s) => s.sqlEditor.renameQueryTab);
11
+ // Local state for modals and editing
12
+ const [queryToDelete, setQueryToDelete] = React.useState(null);
13
+ const [editingQueryId, setEditingQueryId] = React.useState(null);
14
+ const [queryToRename, setQueryToRename] = React.useState(null);
15
+ const createQueryTab = useStoreWithSqlEditor((s) => s.sqlEditor.createQueryTab);
16
+ const deleteQueryTab = useStoreWithSqlEditor((s) => s.sqlEditor.deleteQueryTab);
17
+ // Handle rename query
18
+ const handleStartRename = useCallback((queryId, currentName) => {
19
+ setQueryToRename({ id: queryId, name: currentName });
20
+ }, []);
21
+ const handleFinishRename = useCallback((newName) => {
22
+ if (queryToRename) {
23
+ renameQueryTab(queryToRename.id, newName);
24
+ }
25
+ setQueryToRename(null);
26
+ }, [queryToRename, renameQueryTab]);
27
+ // Handle rename query
28
+ const handleRename = useCallback((queryId, newName) => {
29
+ if (newName.trim() !== '') {
30
+ renameQueryTab(queryId, newName.trim());
31
+ }
32
+ setEditingQueryId(null);
33
+ }, [renameQueryTab]);
34
+ // Handle double click to start editing
35
+ const handleDoubleClick = useCallback((queryId) => {
36
+ setEditingQueryId(queryId);
37
+ }, []);
38
+ // Handle delete query
39
+ const handleDeleteQuery = useCallback((queryId) => {
40
+ // Find the query to check if it's empty
41
+ const queryToDelete = queries.find((q) => q.id === queryId);
42
+ // If query is empty (no content), delete immediately without confirmation
43
+ if (queryToDelete && queryToDelete.query.trim() === '') {
44
+ deleteQueryTab(queryId);
45
+ }
46
+ else {
47
+ // Otherwise, show confirmation modal
48
+ setQueryToDelete(queryId);
49
+ }
50
+ }, [queries, deleteQueryTab]);
51
+ // Handle new query creation
52
+ const handleNewQuery = useCallback(() => {
53
+ return createQueryTab();
54
+ }, [createQueryTab]);
55
+ const handleConfirmDeleteQuery = useCallback(() => {
56
+ if (queryToDelete) {
57
+ deleteQueryTab(queryToDelete);
58
+ setQueryToDelete(null);
59
+ }
60
+ }, [queryToDelete, deleteQueryTab]);
61
+ return (_jsxs(_Fragment, { children: [_jsx(TabsList, { className: cn('h-auto flex-1 flex-wrap', className), children: queries.map((q) => (_jsxs("div", { className: "relative", children: [_jsx(TabsTrigger, { value: q.id, className: "hover:bg-accent min-w-[60px] max-w-[150px] overflow-hidden px-6 py-0 pr-8", children: _jsx("div", { className: "flex h-6 items-center", onDoubleClick: () => handleDoubleClick(q.id), children: editingQueryId !== q.id ? (_jsx("div", { children: q.name })) : (_jsx(EditableText, { value: q.name, onChange: (newName) => handleRename(q.id, newName), className: "h-6 truncate text-sm", isEditing: editingQueryId === q.id, onEditingChange: (isEditing) => {
62
+ if (!isEditing) {
63
+ setEditingQueryId(null);
64
+ }
65
+ } })) }) }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { 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", children: _jsx(MoreVerticalIcon, { className: "h-3 w-3" }) }) }), _jsxs(DropdownMenuContent, { children: [_jsx(DropdownMenuItem, { onClick: () => {
66
+ handleStartRename(q.id, q.name);
67
+ }, children: "Rename" }), queries.length > 1 && (_jsx(DropdownMenuItem, { onClick: () => {
68
+ handleDeleteQuery(q.id);
69
+ }, 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" }) }), _jsx(DeleteSqlQueryModal, { isOpen: queryToDelete !== null, onClose: () => setQueryToDelete(null), onConfirm: handleConfirmDeleteQuery }), _jsx(RenameSqlQueryModal, { isOpen: queryToRename !== null, onClose: () => setQueryToRename(null), initialName: queryToRename?.name ?? '', onRename: handleFinishRename })] }));
70
+ };
71
+ //# sourceMappingURL=QueryEditorPanelTabsList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueryEditorPanelTabsList.js","sourceRoot":"","sources":["../../src/components/QueryEditorPanelTabsList.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n Button,\n cn,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n EditableText,\n TabsList,\n TabsTrigger,\n} from '@sqlrooms/ui';\nimport {MoreVerticalIcon, PlusIcon} from 'lucide-react';\nimport React, {useCallback} from 'react';\nimport {useStoreWithSqlEditor} from '../SqlEditorSlice';\nimport DeleteSqlQueryModal from './DeleteSqlQueryModal';\nimport RenameSqlQueryModal from './RenameSqlQueryModal';\n\nexport const QueryEditorPanelTabsList: React.FC<{className?: string}> = ({\n className,\n}) => {\n const queries = useStoreWithSqlEditor((s) => s.config.sqlEditor.queries);\n\n const renameQueryTab = useStoreWithSqlEditor(\n (s) => s.sqlEditor.renameQueryTab,\n );\n\n // Local state for modals and editing\n const [queryToDelete, setQueryToDelete] = React.useState<string | null>(null);\n const [editingQueryId, setEditingQueryId] = React.useState<string | null>(\n null,\n );\n const [queryToRename, setQueryToRename] = React.useState<{\n id: string;\n name: string;\n } | null>(null);\n\n const createQueryTab = useStoreWithSqlEditor(\n (s) => s.sqlEditor.createQueryTab,\n );\n const deleteQueryTab = useStoreWithSqlEditor(\n (s) => s.sqlEditor.deleteQueryTab,\n );\n\n // Handle rename query\n const handleStartRename = useCallback(\n (queryId: string, currentName: string) => {\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 // Handle rename query\n const handleRename = useCallback(\n (queryId: string, newName: string) => {\n if (newName.trim() !== '') {\n renameQueryTab(queryId, newName.trim());\n }\n setEditingQueryId(null);\n },\n [renameQueryTab],\n );\n\n // Handle double click to start editing\n const handleDoubleClick = useCallback((queryId: string) => {\n setEditingQueryId(queryId);\n }, []);\n\n // Handle delete query\n const handleDeleteQuery = useCallback(\n (queryId: string) => {\n // Find the query to check if it's empty\n const queryToDelete = queries.find((q) => q.id === queryId);\n\n // If query is empty (no content), delete immediately without confirmation\n if (queryToDelete && queryToDelete.query.trim() === '') {\n deleteQueryTab(queryId);\n } else {\n // Otherwise, show confirmation modal\n setQueryToDelete(queryId);\n }\n },\n [queries, deleteQueryTab],\n );\n\n // Handle new query creation\n const handleNewQuery = useCallback(() => {\n return createQueryTab();\n }, [createQueryTab]);\n\n const handleConfirmDeleteQuery = useCallback(() => {\n if (queryToDelete) {\n deleteQueryTab(queryToDelete);\n setQueryToDelete(null);\n }\n }, [queryToDelete, deleteQueryTab]);\n\n return (\n <>\n <TabsList className={cn('h-auto flex-1 flex-wrap', className)}>\n {queries.map((q) => (\n <div key={q.id} className=\"relative\">\n <TabsTrigger\n value={q.id}\n className=\"hover:bg-accent min-w-[60px] max-w-[150px] overflow-hidden px-6 py-0 pr-8\"\n >\n <div\n className=\"flex h-6 items-center\"\n onDoubleClick={() => handleDoubleClick(q.id)}\n >\n {editingQueryId !== q.id ? (\n <div>{q.name}</div>\n ) : (\n <EditableText\n value={q.name}\n onChange={(newName: string) => handleRename(q.id, newName)}\n className=\"h-6 truncate text-sm\"\n isEditing={editingQueryId === q.id}\n onEditingChange={(isEditing) => {\n if (!isEditing) {\n setEditingQueryId(null);\n }\n }}\n />\n )}\n </div>\n </TabsTrigger>\n <DropdownMenu>\n <DropdownMenuTrigger>\n <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\">\n <MoreVerticalIcon className=\"h-3 w-3\" />\n </div>\n </DropdownMenuTrigger>\n <DropdownMenuContent>\n <DropdownMenuItem\n onClick={() => {\n handleStartRename(q.id, q.name);\n }}\n >\n Rename\n </DropdownMenuItem>\n {queries.length > 1 && (\n <DropdownMenuItem\n onClick={() => {\n handleDeleteQuery(q.id);\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 <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 </>\n );\n};\n"]}
@@ -0,0 +1,12 @@
1
+ import { DataTablePaginatedProps } from '@sqlrooms/data-table';
2
+ import React from 'react';
3
+ export interface QueryResultPanelProps {
4
+ /** Custom class name for styling */
5
+ className?: string;
6
+ /** Custom actions to render in the query result panel */
7
+ renderActions?: (query: string) => React.ReactNode;
8
+ /** Custom font size for the table e.g. text-xs, text-sm, text-md, text-lg, text-base */
9
+ fontSize?: DataTablePaginatedProps<any>['fontSize'];
10
+ }
11
+ export declare const QueryResultPanel: React.FC<QueryResultPanelProps>;
12
+ //# sourceMappingURL=QueryResultPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueryResultPanel.d.ts","sourceRoot":"","sources":["../../src/components/QueryResultPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,uBAAuB,EAExB,MAAM,sBAAsB,CAAC;AAU9B,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,WAAW,qBAAqB;IACpC,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC,SAAS,CAAC;IACnD,wFAAwF;IACxF,QAAQ,CAAC,EAAE,uBAAuB,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC;CACrD;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAqG5D,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { DataTablePaginated, useArrowDataTable, } from '@sqlrooms/data-table';
3
+ import { cn, Select, SelectContent, SelectItem, SelectTrigger, SpinnerPane, } from '@sqlrooms/ui';
4
+ import { formatCount } from '@sqlrooms/utils';
5
+ import { isQueryWithResult, useStoreWithSqlEditor } from '../SqlEditorSlice';
6
+ export const QueryResultPanel = ({ className, renderActions, fontSize = 'text-xs', }) => {
7
+ const queryResult = useStoreWithSqlEditor((s) => s.sqlEditor.queryResult);
8
+ const setQueryResultLimit = useStoreWithSqlEditor((s) => s.sqlEditor.setQueryResultLimit);
9
+ const queryResultLimit = useStoreWithSqlEditor((s) => s.sqlEditor.queryResultLimit);
10
+ const arrowTableData = useArrowDataTable(isQueryWithResult(queryResult) ? queryResult.result : undefined);
11
+ if (!queryResult) {
12
+ return null;
13
+ }
14
+ if (queryResult?.status === 'loading') {
15
+ return _jsx(SpinnerPane, { h: "100%" });
16
+ }
17
+ if (queryResult?.status === 'aborted') {
18
+ return (_jsx("div", { className: "p-5 font-mono text-xs leading-tight text-red-500", children: "Query was aborted" }));
19
+ }
20
+ if (queryResult?.status === 'error') {
21
+ return (_jsx("div", { className: "h-full w-full overflow-auto p-5", children: _jsx("pre", { className: "whitespace-pre-line text-xs leading-tight text-red-500", children: queryResult.error }) }));
22
+ }
23
+ if (queryResult?.status === 'success') {
24
+ return (_jsx("div", { className: cn('relative flex h-full w-full flex-grow flex-col overflow-hidden', className), children: isQueryWithResult(queryResult) ? (_jsxs("div", { className: "flex h-full w-full flex-col", children: [_jsx(DataTablePaginated, { ...arrowTableData, className: "flex-grow overflow-hidden", fontSize: fontSize, isFetching: false }), _jsxs("div", { className: "bg-background flex w-full items-center gap-2 px-4 py-1", children: [queryResult.result ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "font-mono text-xs", children: `${formatCount(queryResult.result.numRows ?? 0)} rows` }), _jsxs(Select, { value: queryResultLimit.toString(), onValueChange: (value) => setQueryResultLimit(parseInt(value)), children: [_jsx(SelectTrigger, { className: "h-6 w-fit", children: _jsx("div", { className: "text-xs text-gray-500", children: `Limit results to ${formatCount(queryResultLimit)} rows` }) }), _jsx(SelectContent, { children: [100, 500, 1000].map((limit) => (_jsx(SelectItem, { value: limit.toString(), children: `${formatCount(limit)} rows` }, limit))) })] })] })) : null, _jsx("div", { className: "flex-1" }), renderActions
25
+ ? renderActions(queryResult.lastQueryStatement)
26
+ : undefined] })] })) : (_jsx("pre", { className: "p-4 text-xs leading-tight text-green-500", children: "Successfully executed query" })) }));
27
+ }
28
+ return null;
29
+ };
30
+ //# sourceMappingURL=QueryResultPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueryResultPanel.js","sourceRoot":"","sources":["../../src/components/QueryResultPanel.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n DataTablePaginated,\n DataTablePaginatedProps,\n useArrowDataTable,\n} from '@sqlrooms/data-table';\nimport {\n cn,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SpinnerPane,\n} from '@sqlrooms/ui';\nimport {formatCount} from '@sqlrooms/utils';\nimport React from 'react';\nimport {isQueryWithResult, useStoreWithSqlEditor} from '../SqlEditorSlice';\n\nexport interface QueryResultPanelProps {\n /** Custom class name for styling */\n className?: string;\n /** Custom actions to render in the query result panel */\n renderActions?: (query: string) => React.ReactNode;\n /** Custom font size for the table e.g. text-xs, text-sm, text-md, text-lg, text-base */\n fontSize?: DataTablePaginatedProps<any>['fontSize'];\n}\n\nexport const QueryResultPanel: React.FC<QueryResultPanelProps> = ({\n className,\n renderActions,\n fontSize = 'text-xs',\n}) => {\n const queryResult = useStoreWithSqlEditor((s) => s.sqlEditor.queryResult);\n const setQueryResultLimit = useStoreWithSqlEditor(\n (s) => s.sqlEditor.setQueryResultLimit,\n );\n const queryResultLimit = useStoreWithSqlEditor(\n (s) => s.sqlEditor.queryResultLimit,\n );\n const arrowTableData = useArrowDataTable(\n isQueryWithResult(queryResult) ? queryResult.result : undefined,\n );\n\n if (!queryResult) {\n return null;\n }\n\n if (queryResult?.status === 'loading') {\n return <SpinnerPane h=\"100%\" />;\n }\n\n if (queryResult?.status === 'aborted') {\n return (\n <div className=\"p-5 font-mono text-xs leading-tight text-red-500\">\n Query was aborted\n </div>\n );\n }\n if (queryResult?.status === 'error') {\n return (\n <div className=\"h-full w-full overflow-auto p-5\">\n <pre className=\"whitespace-pre-line text-xs leading-tight text-red-500\">\n {queryResult.error}\n </pre>\n </div>\n );\n }\n\n if (queryResult?.status === 'success') {\n return (\n <div\n className={cn(\n 'relative flex h-full w-full flex-grow flex-col overflow-hidden',\n className,\n )}\n >\n {isQueryWithResult(queryResult) ? (\n <div className=\"flex h-full w-full flex-col\">\n <DataTablePaginated\n {...arrowTableData}\n className=\"flex-grow overflow-hidden\"\n fontSize={fontSize}\n isFetching={false}\n />\n <div className=\"bg-background flex w-full items-center gap-2 px-4 py-1\">\n {queryResult.result ? (\n <>\n <div className=\"font-mono text-xs\">\n {`${formatCount(queryResult.result.numRows ?? 0)} rows`}\n </div>\n\n <Select\n value={queryResultLimit.toString()}\n onValueChange={(value) =>\n setQueryResultLimit(parseInt(value))\n }\n >\n <SelectTrigger className=\"h-6 w-fit\">\n <div className=\"text-xs text-gray-500\">\n {`Limit results to ${formatCount(queryResultLimit)} rows`}\n </div>\n </SelectTrigger>\n <SelectContent>\n {[100, 500, 1000].map((limit) => (\n <SelectItem key={limit} value={limit.toString()}>\n {`${formatCount(limit)} rows`}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </>\n ) : null}\n <div className=\"flex-1\" />\n {renderActions\n ? renderActions(queryResult.lastQueryStatement)\n : undefined}\n </div>\n </div>\n ) : (\n <pre className=\"p-4 text-xs leading-tight text-green-500\">\n Successfully executed query\n </pre>\n )}\n </div>\n );\n }\n\n return null;\n};\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RenameSqlQueryModal.d.ts","sourceRoot":"","sources":["../../src/components/RenameSqlQueryModal.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAWvC,QAAA,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACrC,CAwDA,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, Button, Form, FormControl, FormField, FormItem, FormLabel, FormMessage, Input, DialogDescription, } from '@sqlrooms/ui';
3
+ import { useEffect } from 'react';
4
+ import { useForm } from 'react-hook-form';
5
+ import * as z from 'zod';
6
+ import { zodResolver } from '@hookform/resolvers/zod';
7
+ const formSchema = z.object({
8
+ queryName: z.string().min(1, 'Query name is required'),
9
+ });
10
+ const RenameSqlQueryModal = ({ isOpen, onClose, initialName, onRename }) => {
11
+ const form = useForm({
12
+ resolver: zodResolver(formSchema),
13
+ defaultValues: {
14
+ queryName: initialName,
15
+ },
16
+ });
17
+ useEffect(() => {
18
+ if (isOpen) {
19
+ form.reset({ queryName: initialName });
20
+ }
21
+ }, [isOpen, initialName, form]);
22
+ function onSubmit(values) {
23
+ onRename(values.queryName);
24
+ onClose();
25
+ }
26
+ return (_jsx(Dialog, { open: isOpen, onOpenChange: (open) => !open && onClose(), children: _jsxs(DialogContent, { children: [_jsxs(DialogHeader, { children: [_jsx(DialogTitle, { children: "Rename" }), _jsx(DialogDescription, { children: "Rename the query to a new name." })] }), _jsx(Form, { ...form, children: _jsxs("form", { onSubmit: form.handleSubmit(onSubmit), className: "space-y-4", children: [_jsx(FormField, { control: form.control, name: "queryName", render: ({ field }) => (_jsxs(FormItem, { children: [_jsx(FormLabel, { children: "Query Name" }), _jsx(FormControl, { children: _jsx(Input, { ...field, autoFocus: true, placeholder: "Enter query name" }) }), _jsx(FormMessage, {})] })) }), _jsxs(DialogFooter, { children: [_jsx(Button, { type: "button", variant: "outline", onClick: onClose, children: "Cancel" }), _jsx(Button, { type: "submit", children: "Save" })] })] }) })] }) }));
27
+ };
28
+ export default RenameSqlQueryModal;
29
+ //# sourceMappingURL=RenameSqlQueryModal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RenameSqlQueryModal.js","sourceRoot":"","sources":["../../src/components/RenameSqlQueryModal.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,MAAM,EACN,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,MAAM,EACN,IAAI,EACJ,WAAW,EACX,SAAS,EACT,QAAQ,EACR,SAAS,EACT,WAAW,EACX,KAAK,EACL,iBAAiB,GAClB,MAAM,cAAc,CAAC;AACtB,OAAc,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AACvC,OAAO,EAAC,OAAO,EAAC,MAAM,iBAAiB,CAAC;AACxC,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,EAAC,WAAW,EAAC,MAAM,yBAAyB,CAAC;AAEpD,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1B,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,wBAAwB,CAAC;CACvD,CAAC,CAAC;AAIH,MAAM,mBAAmB,GAKpB,CAAC,EAAC,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAC,EAAE,EAAE;IAChD,MAAM,IAAI,GAAG,OAAO,CAAW;QAC7B,QAAQ,EAAE,WAAW,CAAC,UAAU,CAAC;QACjC,aAAa,EAAE;YACb,SAAS,EAAE,WAAW;SACvB;KACF,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,KAAK,CAAC,EAAC,SAAS,EAAE,WAAW,EAAC,CAAC,CAAC;QACvC,CAAC;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;IAEhC,SAAS,QAAQ,CAAC,MAAgB;QAChC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC3B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,CACL,KAAC,MAAM,IAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,OAAO,EAAE,YAC9D,MAAC,aAAa,eACZ,MAAC,YAAY,eACX,KAAC,WAAW,yBAAqB,EACjC,KAAC,iBAAiB,kDAAoD,IACzD,EACf,KAAC,IAAI,OAAK,IAAI,YACZ,gBAAM,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAC,WAAW,aAChE,KAAC,SAAS,IACR,OAAO,EAAE,IAAI,CAAC,OAAO,EACrB,IAAI,EAAC,WAAW,EAChB,MAAM,EAAE,CAAC,EAAC,KAAK,EAAC,EAAE,EAAE,CAAC,CACnB,MAAC,QAAQ,eACP,KAAC,SAAS,6BAAuB,EACjC,KAAC,WAAW,cACV,KAAC,KAAK,OACA,KAAK,EACT,SAAS,QACT,WAAW,EAAC,kBAAkB,GAC9B,GACU,EACd,KAAC,WAAW,KAAG,IACN,CACZ,GACD,EACF,MAAC,YAAY,eACX,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,EAAC,OAAO,EAAC,SAAS,EAAC,OAAO,EAAE,OAAO,uBAE/C,EACT,KAAC,MAAM,IAAC,IAAI,EAAC,QAAQ,qBAAc,IACtB,IACV,GACF,IACO,GACT,CACV,CAAC;AACJ,CAAC,CAAC;AAEF,eAAe,mBAAmB,CAAC","sourcesContent":["import {\n Dialog,\n DialogContent,\n DialogFooter,\n DialogHeader,\n DialogTitle,\n Button,\n Form,\n FormControl,\n FormField,\n FormItem,\n FormLabel,\n FormMessage,\n Input,\n DialogDescription,\n} from '@sqlrooms/ui';\nimport React, {useEffect} from 'react';\nimport {useForm} from 'react-hook-form';\nimport * as z from 'zod';\nimport {zodResolver} from '@hookform/resolvers/zod';\n\nconst formSchema = z.object({\n queryName: z.string().min(1, 'Query name is required'),\n});\n\ntype FormData = z.infer<typeof formSchema>;\n\nconst RenameSqlQueryModal: React.FC<{\n isOpen: boolean;\n onClose: () => void;\n initialName: string;\n onRename: (newName: string) => void;\n}> = ({isOpen, onClose, initialName, onRename}) => {\n const form = useForm<FormData>({\n resolver: zodResolver(formSchema),\n defaultValues: {\n queryName: initialName,\n },\n });\n\n useEffect(() => {\n if (isOpen) {\n form.reset({queryName: initialName});\n }\n }, [isOpen, initialName, form]);\n\n function onSubmit(values: FormData) {\n onRename(values.queryName);\n onClose();\n }\n\n return (\n <Dialog open={isOpen} onOpenChange={(open) => !open && onClose()}>\n <DialogContent>\n <DialogHeader>\n <DialogTitle>Rename</DialogTitle>\n <DialogDescription>Rename the query to a new name.</DialogDescription>\n </DialogHeader>\n <Form {...form}>\n <form onSubmit={form.handleSubmit(onSubmit)} className=\"space-y-4\">\n <FormField\n control={form.control}\n name=\"queryName\"\n render={({field}) => (\n <FormItem>\n <FormLabel>Query Name</FormLabel>\n <FormControl>\n <Input\n {...field}\n autoFocus\n placeholder=\"Enter query name\"\n />\n </FormControl>\n <FormMessage />\n </FormItem>\n )}\n />\n <DialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={onClose}>\n Cancel\n </Button>\n <Button type=\"submit\">Save</Button>\n </DialogFooter>\n </form>\n </Form>\n </DialogContent>\n </Dialog>\n );\n};\n\nexport default RenameSqlQueryModal;\n"]}
@@ -0,0 +1,15 @@
1
+ import React, { PropsWithChildren } from 'react';
2
+ export type SqlEditorHeaderProps = PropsWithChildren<{
3
+ /** Custom class name for styling */
4
+ className?: string;
5
+ /** The title of the SQL editor */
6
+ title?: string;
7
+ /** Whether to show the documentation panel */
8
+ showDocs?: boolean;
9
+ /** Optional documentation panel component */
10
+ documentationPanel?: React.ReactNode;
11
+ /** Callback when the documentation visibility is toggled */
12
+ onToggleDocs?: (show: boolean) => void;
13
+ }>;
14
+ export declare const SqlEditorHeader: React.FC<SqlEditorHeaderProps>;
15
+ //# sourceMappingURL=SqlEditorHeader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SqlEditorHeader.d.ts","sourceRoot":"","sources":["../../src/components/SqlEditorHeader.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAC,iBAAiB,EAAC,MAAM,OAAO,CAAC;AAM/C,MAAM,MAAM,oBAAoB,GAAG,iBAAiB,CAAC;IACnD,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,6CAA6C;IAC7C,kBAAkB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACrC,4DAA4D;IAC5D,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC,CAAC,CAAC;AAEH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA0B1D,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, cn } from '@sqlrooms/ui';
3
+ import { SqlReferenceButton, SqlReferenceButtonContent, } from './SqlReferenceButton';
4
+ export const SqlEditorHeader = ({ className, title, showDocs, documentationPanel, onToggleDocs, children, }) => {
5
+ return (_jsxs("div", { className: cn('flex w-full items-center gap-2 px-2 py-1', className), children: [title && _jsx("h2", { className: "text-md ml-1 font-semibold", children: title }), children, _jsx("div", { className: "flex-grow" }), documentationPanel ? (_jsx(Button, { size: "sm", variant: showDocs ? 'secondary' : 'outline', onClick: () => onToggleDocs?.(!showDocs), children: _jsx(SqlReferenceButtonContent, {}) })) : (_jsx(SqlReferenceButton, {}))] }));
6
+ };
7
+ //# sourceMappingURL=SqlEditorHeader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SqlEditorHeader.js","sourceRoot":"","sources":["../../src/components/SqlEditorHeader.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,MAAM,EAAE,EAAE,EAAC,MAAM,cAAc,CAAC;AAExC,OAAO,EACL,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,sBAAsB,CAAC;AAe9B,MAAM,CAAC,MAAM,eAAe,GAAmC,CAAC,EAC9D,SAAS,EACT,KAAK,EACL,QAAQ,EACR,kBAAkB,EAClB,YAAY,EACZ,QAAQ,GACT,EAAE,EAAE;IACH,OAAO,CACL,eAAK,SAAS,EAAE,EAAE,CAAC,0CAA0C,EAAE,SAAS,CAAC,aACtE,KAAK,IAAI,aAAI,SAAS,EAAC,4BAA4B,YAAE,KAAK,GAAM,EAChE,QAAQ,EACT,cAAK,SAAS,EAAC,WAAW,GAAG,EAC5B,kBAAkB,CAAC,CAAC,CAAC,CACpB,KAAC,MAAM,IACL,IAAI,EAAC,IAAI,EACT,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,EAC3C,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,EAAE,CAAC,CAAC,QAAQ,CAAC,YAExC,KAAC,yBAAyB,KAAG,GACtB,CACV,CAAC,CAAC,CAAC,CACF,KAAC,kBAAkB,KAAG,CACvB,IACG,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {Button, cn} from '@sqlrooms/ui';\nimport React, {PropsWithChildren} from 'react';\nimport {\n SqlReferenceButton,\n SqlReferenceButtonContent,\n} from './SqlReferenceButton';\n\nexport type SqlEditorHeaderProps = PropsWithChildren<{\n /** Custom class name for styling */\n className?: string;\n /** The title of the SQL editor */\n title?: string;\n /** Whether to show the documentation panel */\n showDocs?: boolean;\n /** Optional documentation panel component */\n documentationPanel?: React.ReactNode;\n /** Callback when the documentation visibility is toggled */\n onToggleDocs?: (show: boolean) => void;\n}>;\n\nexport const SqlEditorHeader: React.FC<SqlEditorHeaderProps> = ({\n className,\n title,\n showDocs,\n documentationPanel,\n onToggleDocs,\n children,\n}) => {\n return (\n <div className={cn('flex w-full items-center gap-2 px-2 py-1', className)}>\n {title && <h2 className=\"text-md ml-1 font-semibold\">{title}</h2>}\n {children}\n <div className=\"flex-grow\" />\n {documentationPanel ? (\n <Button\n size=\"sm\"\n variant={showDocs ? 'secondary' : 'outline'}\n onClick={() => onToggleDocs?.(!showDocs)}\n >\n <SqlReferenceButtonContent />\n </Button>\n ) : (\n <SqlReferenceButton />\n )}\n </div>\n );\n};\n"]}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SqlQueryDataSourcesPanel.d.ts","sourceRoot":"","sources":["../../src/components/SqlQueryDataSourcesPanel.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAC,kBAAkB,EAAC,MAAM,2BAA2B,CAAC;AAgB7D,OAAO,EAAC,EAAE,EAAwB,MAAM,OAAO,CAAC;AAGhD,QAAA,MAAM,wBAAwB,EAAE,EAAE,CAAC;IACjC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gBAAgB,EAAE,kBAAkB,EAAE,CAAC;CACxC,CAoHA,CAAC;AAEF,OAAO,EAAC,wBAAwB,EAAC,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SqlQueryDataSourcesPanel.js","sourceRoot":"","sources":["../../src/components/SqlQueryDataSourcesPanel.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n DataSourceStatus,\n useBaseProjectBuilderStore,\n} from '@sqlrooms/project-builder';\nimport {SqlQueryDataSource} from '@sqlrooms/project-builder';\nimport {\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from '@sqlrooms/ui';\nimport {\n EllipsisIcon,\n FileIcon,\n PencilIcon,\n PlusIcon,\n RefreshCcwIcon,\n XIcon,\n} from 'lucide-react';\nimport {FC, useCallback, useState} from 'react';\nimport CreateTableModal from './CreateTableModal';\n\nconst SqlQueryDataSourcesPanel: FC<{\n isReadOnly?: boolean;\n queryDataSources: SqlQueryDataSource[];\n}> = ({queryDataSources, isReadOnly}) => {\n const [selectedDataSource, setSelectedDataSource] =\n useState<SqlQueryDataSource>();\n const [isOpen, setIsOpen] = useState(false);\n const dataSourceStates = useBaseProjectBuilderStore(\n (state) => state.project.dataSourceStates,\n );\n const removeSqlQueryDataSource = useBaseProjectBuilderStore(\n (state) => state.project.removeSqlQueryDataSource,\n );\n\n const handleEdit = useCallback((dataSource: SqlQueryDataSource) => {\n setSelectedDataSource(dataSource);\n setIsOpen(true);\n }, []);\n\n const handleClose = useCallback(() => {\n setIsOpen(false);\n setSelectedDataSource(undefined);\n }, []);\n\n const handleRemove = useCallback(\n (dataSource: SqlQueryDataSource) => {\n const {tableName} = dataSource;\n removeSqlQueryDataSource(tableName);\n },\n [removeSqlQueryDataSource],\n );\n\n const addOrUpdateSqlQueryDataSource = useBaseProjectBuilderStore(\n (state) => state.project.addOrUpdateSqlQueryDataSource,\n );\n\n return (\n <div className=\"flex flex-grow flex-col overflow-auto\">\n <div className=\"flex flex-col items-stretch\">\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => setIsOpen(true)}\n disabled={isReadOnly}\n >\n <PlusIcon className=\"mr-2 h-4 w-4\" />\n Add\n </Button>\n </div>\n <CreateTableModal\n isOpen={isOpen}\n onClose={handleClose}\n editDataSource={selectedDataSource}\n query=\"\"\n onAddOrUpdateSqlQuery={addOrUpdateSqlQueryDataSource}\n />\n\n <div className=\"flex flex-grow flex-col overflow-auto\">\n {queryDataSources.map((dataSource) => (\n <div key={dataSource.tableName} className=\"flex flex-col gap-1 p-2\">\n <div className=\"flex cursor-pointer flex-row items-center gap-1\">\n <div className=\"w-[15px] flex-none\">\n <FileIcon className=\"w-[15px]\" />\n </div>\n <div className=\"flex-1 overflow-hidden text-ellipsis\">\n <span className=\"break-words text-xs\">\n {dataSource.tableName}\n </span>\n </div>\n <div className=\"flex-none\">\n {!isReadOnly ? (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <Button\n size=\"icon\"\n variant=\"ghost\"\n className=\"text-muted-foreground h-6 w-6\"\n >\n <EllipsisIcon className=\"h-5 w-5\" />\n </Button>\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onClick={() => handleEdit(dataSource)}>\n <PencilIcon className=\"mr-2 h-4 w-4\" />\n Edit\n </DropdownMenuItem>\n <DropdownMenuItem disabled>\n <RefreshCcwIcon className=\"mr-2 h-4 w-4\" />\n Refresh\n </DropdownMenuItem>\n <DropdownMenuItem\n onClick={() => handleRemove(dataSource)}\n >\n <XIcon className=\"mr-2 h-4 w-4\" />\n Remove from project\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n ) : null}\n </div>\n </div>\n <div className=\"flex flex-row items-center gap-1\">\n {dataSourceStates[dataSource.tableName]?.status ===\n DataSourceStatus.ERROR ? (\n <div className=\"bg-destructive/15 text-destructive flex-1 rounded p-1 text-xs\">\n {dataSourceStates[dataSource.tableName]?.message}\n </div>\n ) : dataSourceStates[dataSource.tableName]?.status ===\n DataSourceStatus.FETCHING ? (\n <div className=\"bg-secondary h-1 w-full overflow-hidden rounded\">\n <div className=\"bg-primary h-full animate-pulse\" />\n </div>\n ) : null}\n </div>\n </div>\n ))}\n </div>\n </div>\n );\n};\n\nexport {SqlQueryDataSourcesPanel};\n"]}
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ export declare const SqlReferenceButton: React.FC<{
3
+ className?: string;
4
+ text?: string;
5
+ icon?: React.ReactNode;
6
+ }>;
7
+ export declare const SqlReferenceButtonContent: React.FC<{
8
+ className?: string;
9
+ text?: string;
10
+ icon?: React.ReactNode;
11
+ }>;
12
+ //# sourceMappingURL=SqlReferenceButton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SqlReferenceButton.d.ts","sourceRoot":"","sources":["../../src/components/SqlReferenceButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACxB,CAYA,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,KAAK,CAAC,EAAE,CAAC;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACxB,CAOA,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, cn } from '@sqlrooms/ui';
3
+ import { BookOpenIcon } from 'lucide-react';
4
+ export const SqlReferenceButton = ({ className, text, icon }) => {
5
+ return (_jsx(Button, { asChild: true, size: "sm", variant: "outline", className: cn(className), children: _jsx("a", { href: "https://duckdb.org/docs/sql/introduction", target: "_blank", rel: "noreferrer", children: _jsx(SqlReferenceButtonContent, { text: text, icon: icon }) }) }));
6
+ };
7
+ export const SqlReferenceButtonContent = ({ className, text = 'SQL reference', icon = _jsx(BookOpenIcon, {}) }) => {
8
+ return (_jsxs("div", { className: cn('flex items-center gap-2', className), children: [icon, _jsx("span", { className: "text-xs", children: text })] }));
9
+ };
10
+ //# sourceMappingURL=SqlReferenceButton.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SqlReferenceButton.js","sourceRoot":"","sources":["../../src/components/SqlReferenceButton.tsx"],"names":[],"mappings":";AACA,OAAO,EAAC,MAAM,EAAE,EAAE,EAAC,MAAM,cAAc,CAAC;AACxC,OAAO,EAAC,YAAY,EAAC,MAAM,cAAc,CAAC;AAE1C,MAAM,CAAC,MAAM,kBAAkB,GAI1B,CAAC,EAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAC,EAAE,EAAE;IAC/B,OAAO,CACL,KAAC,MAAM,IAAC,OAAO,QAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAC,SAAS,EAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,YAClE,YACE,IAAI,EAAC,0CAA0C,EAC/C,MAAM,EAAC,QAAQ,EACf,GAAG,EAAC,YAAY,YAEhB,KAAC,yBAAyB,IAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,GAAI,GACnD,GACG,CACV,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,yBAAyB,GAIjC,CAAC,EAAC,SAAS,EAAE,IAAI,GAAG,eAAe,EAAE,IAAI,GAAG,KAAC,YAAY,KAAG,EAAC,EAAE,EAAE;IACpE,OAAO,CACL,eAAK,SAAS,EAAE,EAAE,CAAC,yBAAyB,EAAE,SAAS,CAAC,aACrD,IAAI,EACL,eAAM,SAAS,EAAC,SAAS,YAAE,IAAI,GAAQ,IACnC,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import React from 'react';\nimport {Button, cn} from '@sqlrooms/ui';\nimport {BookOpenIcon} from 'lucide-react';\n\nexport const SqlReferenceButton: React.FC<{\n className?: string;\n text?: string;\n icon?: React.ReactNode;\n}> = ({className, text, icon}) => {\n return (\n <Button asChild size=\"sm\" variant=\"outline\" className={cn(className)}>\n <a\n href=\"https://duckdb.org/docs/sql/introduction\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n <SqlReferenceButtonContent text={text} icon={icon} />\n </a>\n </Button>\n );\n};\n\nexport const SqlReferenceButtonContent: React.FC<{\n className?: string;\n text?: string;\n icon?: React.ReactNode;\n}> = ({className, text = 'SQL reference', icon = <BookOpenIcon />}) => {\n return (\n <div className={cn('flex items-center gap-2', className)}>\n {icon}\n <span className=\"text-xs\">{text}</span>\n </div>\n );\n};\n"]}
@@ -0,0 +1,13 @@
1
+ import React from 'react';
2
+ export interface TableStructurePanelProps {
3
+ /** Custom class name for styling */
4
+ className?: string;
5
+ /** The database schema to use. Defaults to 'main'.
6
+ * If '*' is provided, all tables will be shown.
7
+ * If a function is provided, it will be used to filter the tables. */
8
+ schema?: string | ((name: string) => boolean);
9
+ /** Callback when a table is selected */
10
+ onTableSelect?: (table: string | undefined) => void;
11
+ }
12
+ export declare const TableStructurePanel: React.FC<TableStructurePanelProps>;
13
+ //# sourceMappingURL=TableStructurePanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TableStructurePanel.d.ts","sourceRoot":"","sources":["../../src/components/TableStructurePanel.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAgB,MAAM,OAAO,CAAC;AAGrC,MAAM,WAAW,wBAAwB;IACvC,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;0EAEsE;IACtE,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,CAAC;IAC9C,wCAAwC;IACxC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;CACrD;AAED,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAmClE,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { TableSchemaTree } from '@sqlrooms/schema-tree';
3
+ import { cn, SpinnerPane } from '@sqlrooms/ui';
4
+ import { useMemo } from 'react';
5
+ import { useStoreWithSqlEditor } from '../SqlEditorSlice';
6
+ export const TableStructurePanel = ({ className, schema = '*', }) => {
7
+ // Get state from store
8
+ const schemaTrees = useStoreWithSqlEditor((s) => s.db.schemaTrees);
9
+ const filteredSchemaTrees = useMemo(() => {
10
+ if (schema === '*') {
11
+ return schemaTrees;
12
+ }
13
+ if (typeof schema === 'function') {
14
+ return schemaTrees?.filter((tree) => schema(tree.object.name));
15
+ }
16
+ return schemaTrees?.filter((tree) => tree.object.name === schema);
17
+ }, [schema, schemaTrees]);
18
+ const isRefreshing = useStoreWithSqlEditor((s) => s.db.isRefreshingTableSchemas);
19
+ return (_jsxs("div", { className: cn('relative flex h-full flex-col gap-2 overflow-auto px-1 py-2', className), children: [filteredSchemaTrees && (_jsx(TableSchemaTree, { schemaTrees: filteredSchemaTrees })), isRefreshing && (_jsx(SpinnerPane, { className: "bg-background/80 absolute inset-0 h-full" }))] }));
20
+ };
21
+ //# sourceMappingURL=TableStructurePanel.js.map