@sqlrooms/vega 0.29.0-rc.1 → 0.29.0-rc.2
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/dist/VegaChartActions.js +1 -1
- package/dist/VegaChartActions.js.map +1 -1
- package/dist/VegaChartTool.d.ts +47 -26
- package/dist/VegaChartTool.d.ts.map +1 -1
- package/dist/VegaChartTool.js +61 -35
- package/dist/VegaChartTool.js.map +1 -1
- package/dist/VegaChartToolResult.d.ts +8 -20
- package/dist/VegaChartToolResult.d.ts.map +1 -1
- package/dist/VegaChartToolResult.js +8 -34
- package/dist/VegaChartToolResult.js.map +1 -1
- package/dist/VegaEditAction.d.ts +4 -9
- package/dist/VegaEditAction.d.ts.map +1 -1
- package/dist/VegaEditAction.js +9 -12
- package/dist/VegaEditAction.js.map +1 -1
- package/dist/VegaLiteArrowChart.d.ts.map +1 -1
- package/dist/VegaLiteArrowChart.js +1 -0
- package/dist/VegaLiteArrowChart.js.map +1 -1
- package/dist/VegaLiteChart.d.ts +44 -0
- package/dist/VegaLiteChart.d.ts.map +1 -0
- package/dist/VegaLiteChart.js +134 -0
- package/dist/VegaLiteChart.js.map +1 -0
- package/dist/VegaLiteSqlChart.js +1 -1
- package/dist/VegaLiteSqlChart.js.map +1 -1
- package/dist/editor/VegaCodeMirrorEditor.d.ts +15 -0
- package/dist/editor/VegaCodeMirrorEditor.d.ts.map +1 -0
- package/dist/editor/VegaCodeMirrorEditor.js +23 -0
- package/dist/editor/VegaCodeMirrorEditor.js.map +1 -0
- package/dist/editor/VegaMonacoEditor.d.ts +5 -0
- package/dist/editor/VegaMonacoEditor.d.ts.map +1 -1
- package/dist/editor/VegaMonacoEditor.js +2 -0
- package/dist/editor/VegaMonacoEditor.js.map +1 -1
- package/dist/editor/VegaSpecEditorPanel.d.ts.map +1 -1
- package/dist/editor/VegaSpecEditorPanel.js +11 -7
- package/dist/editor/VegaSpecEditorPanel.js.map +1 -1
- package/dist/editor/VegaSqlEditorPanel.d.ts +1 -1
- package/dist/editor/VegaSqlEditorPanel.d.ts.map +1 -1
- package/dist/editor/VegaSqlEditorPanel.js +9 -10
- package/dist/editor/VegaSqlEditorPanel.js.map +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/package.json +11 -10
package/dist/VegaChartActions.js
CHANGED
|
@@ -18,6 +18,6 @@ import { cn } from '@sqlrooms/ui';
|
|
|
18
18
|
* ```
|
|
19
19
|
*/
|
|
20
20
|
export const VegaChartActions = ({ children, className, }) => {
|
|
21
|
-
return (_jsx("div", { className: cn('vega-actions bg-background pointer-
|
|
21
|
+
return (_jsx("div", { className: cn('vega-actions bg-background pointer-events-none absolute top-1 right-0 z-10 flex items-center gap-1 opacity-0 transition-opacity peer-focus-within:pointer-events-auto peer-focus-within:opacity-100 peer-hover:pointer-events-auto peer-hover:opacity-100 focus-within:pointer-events-auto focus-within:opacity-100 hover:pointer-events-auto hover:opacity-100 pointer-coarse:pointer-events-auto pointer-coarse:opacity-100', className), children: children }));
|
|
22
22
|
};
|
|
23
23
|
//# sourceMappingURL=VegaChartActions.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VegaChartActions.js","sourceRoot":"","sources":["../src/VegaChartActions.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,EAAE,EAAC,MAAM,cAAc,CAAC;AAchC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAoC,CAAC,EAChE,QAAQ,EACR,SAAS,GACV,EAAE,EAAE;IACH,OAAO,CACL,cACE,SAAS,EAAE,EAAE,CACX,+ZAA+Z,EAC/Z,SAAS,CACV,YAEA,QAAQ,GACL,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {cn} from '@sqlrooms/ui';\nimport React from 'react';\n\nexport interface VegaChartActionsProps {\n /**\n * Action components to render in the toolbar\n */\n children: React.ReactNode;\n /**\n * Additional CSS classes for the container\n */\n className?: string;\n}\n\n/**\n * Container component for chart actions toolbar.\n * Positions actions as an overlay in the top-right corner of the chart.\n *\n * @example\n * ```tsx\n * <VegaLiteArrowChart spec={spec} arrowTable={data}>\n * <VegaChartActions>\n * <VegaExportAction />\n * <Separator orientation=\"vertical\" className=\"h-4\" />\n * <Button size=\"xs\" variant=\"ghost\" onClick={handleRefresh}>\n * <RefreshCw className=\"h-4 w-4\" />\n * </Button>\n * </VegaChartActions>\n * </VegaLiteArrowChart>\n * ```\n */\nexport const VegaChartActions: React.FC<VegaChartActionsProps> = ({\n children,\n className,\n}) => {\n return (\n <div\n className={cn(\n 'vega-actions bg-background pointer-
|
|
1
|
+
{"version":3,"file":"VegaChartActions.js","sourceRoot":"","sources":["../src/VegaChartActions.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAC,EAAE,EAAC,MAAM,cAAc,CAAC;AAchC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAoC,CAAC,EAChE,QAAQ,EACR,SAAS,GACV,EAAE,EAAE;IACH,OAAO,CACL,cACE,SAAS,EAAE,EAAE,CACX,+ZAA+Z,EAC/Z,SAAS,CACV,YAEA,QAAQ,GACL,CACP,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import {cn} from '@sqlrooms/ui';\nimport React from 'react';\n\nexport interface VegaChartActionsProps {\n /**\n * Action components to render in the toolbar\n */\n children: React.ReactNode;\n /**\n * Additional CSS classes for the container\n */\n className?: string;\n}\n\n/**\n * Container component for chart actions toolbar.\n * Positions actions as an overlay in the top-right corner of the chart.\n *\n * @example\n * ```tsx\n * <VegaLiteArrowChart spec={spec} arrowTable={data}>\n * <VegaChartActions>\n * <VegaExportAction />\n * <Separator orientation=\"vertical\" className=\"h-4\" />\n * <Button size=\"xs\" variant=\"ghost\" onClick={handleRefresh}>\n * <RefreshCw className=\"h-4 w-4\" />\n * </Button>\n * </VegaChartActions>\n * </VegaLiteArrowChart>\n * ```\n */\nexport const VegaChartActions: React.FC<VegaChartActionsProps> = ({\n children,\n className,\n}) => {\n return (\n <div\n className={cn(\n 'vega-actions bg-background pointer-events-none absolute top-1 right-0 z-10 flex items-center gap-1 opacity-0 transition-opacity peer-focus-within:pointer-events-auto peer-focus-within:opacity-100 peer-hover:pointer-events-auto peer-hover:opacity-100 focus-within:pointer-events-auto focus-within:opacity-100 hover:pointer-events-auto hover:opacity-100 pointer-coarse:pointer-events-auto pointer-coarse:opacity-100',\n className,\n )}\n >\n {children}\n </div>\n );\n};\n"]}
|
package/dist/VegaChartTool.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
import { TopLevelSpec } from 'vega-lite';
|
|
3
|
+
import type { DuckDbConnector } from '@sqlrooms/duckdb';
|
|
4
|
+
/**
|
|
5
|
+
* Creates a SQL validator that checks queries by executing `SELECT 1 FROM (<query>) LIMIT 1`.
|
|
6
|
+
* Returns an error message if the query fails or produces no rows.
|
|
7
|
+
*/
|
|
8
|
+
export declare function createSqlValidator(getConnector: () => DuckDbConnector | Promise<DuckDbConnector>): NonNullable<VegaChartToolOptions['validateSql']>;
|
|
5
9
|
/**
|
|
6
10
|
* Zod schema for the VegaChart tool parameters
|
|
7
11
|
*/
|
|
@@ -11,20 +15,13 @@ export declare const VegaChartToolParameters: z.ZodObject<{
|
|
|
11
15
|
reasoning: z.ZodString;
|
|
12
16
|
}, z.core.$strip>;
|
|
13
17
|
export type VegaChartToolParameters = z.infer<typeof VegaChartToolParameters>;
|
|
14
|
-
export type
|
|
15
|
-
sqlQuery: z.ZodString;
|
|
16
|
-
vegaLiteSpec: z.ZodString;
|
|
17
|
-
reasoning: z.ZodString;
|
|
18
|
-
}>;
|
|
19
|
-
export type VegaChartToolLlmResult = {
|
|
18
|
+
export type VegaChartToolOutput = {
|
|
20
19
|
success: boolean;
|
|
21
20
|
details: string;
|
|
22
|
-
};
|
|
23
|
-
export type VegaChartToolAdditionalData = {
|
|
24
21
|
sqlQuery: string;
|
|
25
|
-
vegaLiteSpec:
|
|
22
|
+
vegaLiteSpec: TopLevelSpec | null;
|
|
23
|
+
error?: string;
|
|
26
24
|
};
|
|
27
|
-
export type VegaChartToolContext = unknown;
|
|
28
25
|
/**
|
|
29
26
|
* Default description for the VegaChart tool
|
|
30
27
|
*/
|
|
@@ -38,19 +35,21 @@ export type VegaChartToolOptions = {
|
|
|
38
35
|
*/
|
|
39
36
|
description?: string;
|
|
40
37
|
/**
|
|
41
|
-
*
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Which editors to show when editing
|
|
51
|
-
* @default 'both'
|
|
38
|
+
* Optional callback to validate the SQL query before rendering the chart.
|
|
39
|
+
* When provided, the tool will execute this function to catch SQL errors
|
|
40
|
+
* or empty results early, so the LLM can fix the query and retry.
|
|
41
|
+
*
|
|
42
|
+
* The function receives the SQL query string and an optional AbortSignal,
|
|
43
|
+
* and should return `{valid: true}` or `{valid: false, error: string}`.
|
|
44
|
+
*
|
|
45
|
+
* For performance, implementations should use `LIMIT 1` or equivalent.
|
|
52
46
|
*/
|
|
53
|
-
|
|
47
|
+
validateSql?: (sqlQuery: string, abortSignal?: AbortSignal) => Promise<{
|
|
48
|
+
valid: true;
|
|
49
|
+
} | {
|
|
50
|
+
valid: false;
|
|
51
|
+
error: string;
|
|
52
|
+
}>;
|
|
54
53
|
};
|
|
55
54
|
/**
|
|
56
55
|
* Creates a VegaLite chart visualization tool for AI assistants
|
|
@@ -60,5 +59,27 @@ export type VegaChartToolOptions = {
|
|
|
60
59
|
* @param options.editorMode - Which editors to show ('spec', 'sql', 'both', 'none')
|
|
61
60
|
* @returns A tool that can be used with the AI assistant
|
|
62
61
|
*/
|
|
63
|
-
export declare function createVegaChartTool({ description,
|
|
62
|
+
export declare function createVegaChartTool({ description, validateSql, }?: VegaChartToolOptions): import("ai").Tool<{
|
|
63
|
+
sqlQuery: string;
|
|
64
|
+
vegaLiteSpec: string;
|
|
65
|
+
reasoning: string;
|
|
66
|
+
}, {
|
|
67
|
+
success: boolean;
|
|
68
|
+
details: string;
|
|
69
|
+
sqlQuery: string;
|
|
70
|
+
vegaLiteSpec: null;
|
|
71
|
+
error?: undefined;
|
|
72
|
+
} | {
|
|
73
|
+
success: boolean;
|
|
74
|
+
details: string;
|
|
75
|
+
sqlQuery: string;
|
|
76
|
+
vegaLiteSpec: TopLevelSpec;
|
|
77
|
+
error?: undefined;
|
|
78
|
+
} | {
|
|
79
|
+
success: boolean;
|
|
80
|
+
details: string;
|
|
81
|
+
error: string;
|
|
82
|
+
sqlQuery: string;
|
|
83
|
+
vegaLiteSpec: null;
|
|
84
|
+
}>;
|
|
64
85
|
//# sourceMappingURL=VegaChartTool.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VegaChartTool.d.ts","sourceRoot":"","sources":["../src/VegaChartTool.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"VegaChartTool.d.ts","sourceRoot":"","sources":["../src/VegaChartTool.tsx"],"names":[],"mappings":"AACA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,EAAU,YAAY,EAAC,MAAM,WAAW,CAAC;AAEhD,OAAO,KAAK,EAAC,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAEtD;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,GAC7D,WAAW,CAAC,oBAAoB,CAAC,aAAa,CAAC,CAAC,CAmBlD;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;iBAIlC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE9E,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,8BAA8B,smCAY4I,CAAC;AAExL;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,CACZ,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,WAAW,KACtB,OAAO,CAAC;QAAC,KAAK,EAAE,IAAI,CAAA;KAAC,GAAG;QAAC,KAAK,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAC,CAAC,CAAC;CAC7D,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,WAA4C,EAC5C,WAAW,GACZ,GAAE,oBAAyB;;;;;;;;;;;;;;;;;;;;;;GAqE3B"}
|
package/dist/VegaChartTool.js
CHANGED
|
@@ -1,9 +1,29 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { tool } from 'ai';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
-
import { VegaChartToolResult, } from './VegaChartToolResult';
|
|
4
3
|
import { compile } from 'vega-lite';
|
|
5
4
|
import { parse as vegaParse } from 'vega';
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Creates a SQL validator that checks queries by executing `SELECT 1 FROM (<query>) LIMIT 1`.
|
|
7
|
+
* Returns an error message if the query fails or produces no rows.
|
|
8
|
+
*/
|
|
9
|
+
export function createSqlValidator(getConnector) {
|
|
10
|
+
return async (sqlQuery, abortSignal) => {
|
|
11
|
+
try {
|
|
12
|
+
const connector = await getConnector();
|
|
13
|
+
const result = await connector.query(`SELECT 1 FROM (${sqlQuery}) AS __validate LIMIT 1`, { signal: abortSignal });
|
|
14
|
+
if (result.numRows === 0) {
|
|
15
|
+
return { valid: false, error: 'Query returned no rows' };
|
|
16
|
+
}
|
|
17
|
+
return { valid: true };
|
|
18
|
+
}
|
|
19
|
+
catch (e) {
|
|
20
|
+
return {
|
|
21
|
+
valid: false,
|
|
22
|
+
error: e instanceof Error ? e.message : String(e),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
7
27
|
/**
|
|
8
28
|
* Zod schema for the VegaChart tool parameters
|
|
9
29
|
*/
|
|
@@ -36,65 +56,71 @@ Best practices for creating charts:
|
|
|
36
56
|
* @param options.editorMode - Which editors to show ('spec', 'sql', 'both', 'none')
|
|
37
57
|
* @returns A tool that can be used with the AI assistant
|
|
38
58
|
*/
|
|
39
|
-
export function createVegaChartTool({ description = DEFAULT_VEGA_CHART_DESCRIPTION,
|
|
40
|
-
return {
|
|
41
|
-
name: 'chart',
|
|
59
|
+
export function createVegaChartTool({ description = DEFAULT_VEGA_CHART_DESCRIPTION, validateSql, } = {}) {
|
|
60
|
+
return tool({
|
|
42
61
|
description,
|
|
43
|
-
|
|
62
|
+
inputSchema: VegaChartToolParameters,
|
|
44
63
|
execute: async (params, options) => {
|
|
45
64
|
const abortSignal = options?.abortSignal;
|
|
46
65
|
const { sqlQuery, vegaLiteSpec } = params;
|
|
47
66
|
try {
|
|
48
|
-
// Check if aborted before starting
|
|
49
67
|
if (abortSignal?.aborted) {
|
|
50
68
|
throw new Error('Chart creation was aborted');
|
|
51
69
|
}
|
|
70
|
+
if (validateSql) {
|
|
71
|
+
const validation = await validateSql(sqlQuery, abortSignal);
|
|
72
|
+
if (!validation.valid) {
|
|
73
|
+
return {
|
|
74
|
+
success: false,
|
|
75
|
+
details: `SQL query failed: ${validation.error}. Please fix the sqlQuery and call this tool again.`,
|
|
76
|
+
sqlQuery,
|
|
77
|
+
vegaLiteSpec: null,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
52
81
|
const parsedVegaLiteSpec = JSON.parse(vegaLiteSpec);
|
|
53
|
-
// Validate/spec-check by compiling to Vega and attempting to parse it.
|
|
54
|
-
// - compile() can throw on invalid Vega-Lite specs
|
|
55
|
-
// - vegaParse() will throw if the compiled Vega spec is invalid
|
|
56
82
|
let vegaWarnings = [];
|
|
57
83
|
try {
|
|
58
84
|
const compiled = compile(parsedVegaLiteSpec);
|
|
59
|
-
// vega-lite's compile() may expose warnings at runtime, but types don't include it
|
|
60
85
|
vegaWarnings = compiled.warnings ?? [];
|
|
61
|
-
// This will throw if the compiled Vega spec is invalid
|
|
62
86
|
vegaParse(compiled.spec);
|
|
63
87
|
}
|
|
64
88
|
catch (e) {
|
|
65
89
|
const message = e instanceof Error ? e.message : String(e);
|
|
66
90
|
return {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
91
|
+
success: false,
|
|
92
|
+
details: `Invalid Vega-Lite spec: ${message}`,
|
|
93
|
+
sqlQuery: '',
|
|
94
|
+
vegaLiteSpec: null,
|
|
71
95
|
};
|
|
72
96
|
}
|
|
73
|
-
// data object of the vegaLiteSpec and sqlQuery
|
|
74
|
-
// it is not used yet, but we can use it to create a JSON editor for user to edit the vegaLiteSpec so that chart can be updated
|
|
75
97
|
return {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
additionalData: {
|
|
83
|
-
sqlQuery,
|
|
84
|
-
vegaLiteSpec: parsedVegaLiteSpec,
|
|
85
|
-
},
|
|
98
|
+
success: true,
|
|
99
|
+
details: vegaWarnings.length > 0
|
|
100
|
+
? `Chart created successfully with warnings:\n- ${vegaWarnings.join('\n- ')}`
|
|
101
|
+
: 'Chart created successfully.',
|
|
102
|
+
sqlQuery,
|
|
103
|
+
vegaLiteSpec: parsedVegaLiteSpec,
|
|
86
104
|
};
|
|
87
105
|
}
|
|
88
106
|
catch (error) {
|
|
89
107
|
return {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
108
|
+
success: false,
|
|
109
|
+
details: `Not a valid JSON object: ${error}`,
|
|
110
|
+
error: error instanceof Error ? error.message : String(error),
|
|
111
|
+
sqlQuery: '',
|
|
112
|
+
vegaLiteSpec: null,
|
|
94
113
|
};
|
|
95
114
|
}
|
|
96
115
|
},
|
|
97
|
-
|
|
98
|
-
|
|
116
|
+
toModelOutput: ({ output }) => ({
|
|
117
|
+
type: 'text',
|
|
118
|
+
value: JSON.stringify({
|
|
119
|
+
success: output.success,
|
|
120
|
+
details: output.details,
|
|
121
|
+
...(output.error ? { error: output.error } : {}),
|
|
122
|
+
}),
|
|
123
|
+
}),
|
|
124
|
+
});
|
|
99
125
|
}
|
|
100
126
|
//# sourceMappingURL=VegaChartTool.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VegaChartTool.js","sourceRoot":"","sources":["../src/VegaChartTool.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"VegaChartTool.js","sourceRoot":"","sources":["../src/VegaChartTool.tsx"],"names":[],"mappings":"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","sourcesContent":["import {tool} from 'ai';\nimport {z} from 'zod';\nimport {compile, TopLevelSpec} from 'vega-lite';\nimport {parse as vegaParse} from 'vega';\nimport type {DuckDbConnector} from '@sqlrooms/duckdb';\n\n/**\n * Creates a SQL validator that checks queries by executing `SELECT 1 FROM (<query>) LIMIT 1`.\n * Returns an error message if the query fails or produces no rows.\n */\nexport function createSqlValidator(\n getConnector: () => DuckDbConnector | Promise<DuckDbConnector>,\n): NonNullable<VegaChartToolOptions['validateSql']> {\n return async (sqlQuery, abortSignal) => {\n try {\n const connector = await getConnector();\n const result = await connector.query(\n `SELECT 1 FROM (${sqlQuery}) AS __validate LIMIT 1`,\n {signal: abortSignal},\n );\n if (result.numRows === 0) {\n return {valid: false, error: 'Query returned no rows'};\n }\n return {valid: true};\n } catch (e) {\n return {\n valid: false,\n error: e instanceof Error ? e.message : String(e),\n };\n }\n };\n}\n\n/**\n * Zod schema for the VegaChart tool parameters\n */\nexport const VegaChartToolParameters = z.object({\n sqlQuery: z.string(),\n vegaLiteSpec: z.string(),\n reasoning: z.string(),\n});\n\nexport type VegaChartToolParameters = z.infer<typeof VegaChartToolParameters>;\n\nexport type VegaChartToolOutput = {\n success: boolean;\n details: string;\n sqlQuery: string;\n vegaLiteSpec: TopLevelSpec | null;\n error?: string;\n};\n\n/**\n * Default description for the VegaChart tool\n */\nexport const DEFAULT_VEGA_CHART_DESCRIPTION = `A tool for creating VegaLite charts based on the schema of the SQL query result from the \"query\" tool.\nIn the response:\n- omit the data from the vegaLiteSpec\n- provide an sql query in sqlQuery instead.\n\nBest practices for creating charts:\n- try to use strptime to convert e.g. YYYYMMDD string format to a proper type (date, datetime, etc.)\n- try to set the top-level width property to \"container\", so the chart will stretch to the full width of its parent container.\n- for bar charts with few categories (<= 5), widen bars by reducing band padding on the x scale:\n - For 2-3 categories: set \"encoding.x.scale.paddingInner\" to 0.2 and \"paddingOuter\" to 0.1 for optimal bar width with clear separation\n - For 4-5 categories: set \"encoding.x.scale.paddingInner\" to 0.1 and \"paddingOuter\" to 0.05 for narrower spacing\n - Adjust to lower values (0.05/0.02 or 0/0) only if user specifically requests maximum bar width\n- If the chart uses an encoding channel like color, shape, or size to represent a data field, then include a legend object in that channel's encoding (unless explicitly told not to).`;\n\n/**\n * Options for creating a VegaChart tool\n */\nexport type VegaChartToolOptions = {\n /**\n * Custom description for the tool\n */\n description?: string;\n /**\n * Optional callback to validate the SQL query before rendering the chart.\n * When provided, the tool will execute this function to catch SQL errors\n * or empty results early, so the LLM can fix the query and retry.\n *\n * The function receives the SQL query string and an optional AbortSignal,\n * and should return `{valid: true}` or `{valid: false, error: string}`.\n *\n * For performance, implementations should use `LIMIT 1` or equivalent.\n */\n validateSql?: (\n sqlQuery: string,\n abortSignal?: AbortSignal,\n ) => Promise<{valid: true} | {valid: false; error: string}>;\n};\n\n/**\n * Creates a VegaLite chart visualization tool for AI assistants\n * @param options - Configuration options for the VegaChart tool\n * @param options.description - Custom description for the tool (defaults to a standard description)\n * @param options.editable - Whether editing is enabled (defaults to true)\n * @param options.editorMode - Which editors to show ('spec', 'sql', 'both', 'none')\n * @returns A tool that can be used with the AI assistant\n */\nexport function createVegaChartTool({\n description = DEFAULT_VEGA_CHART_DESCRIPTION,\n validateSql,\n}: VegaChartToolOptions = {}) {\n return tool({\n description,\n inputSchema: VegaChartToolParameters,\n execute: async (params, options) => {\n const abortSignal = options?.abortSignal;\n const {sqlQuery, vegaLiteSpec} = params;\n try {\n if (abortSignal?.aborted) {\n throw new Error('Chart creation was aborted');\n }\n\n if (validateSql) {\n const validation = await validateSql(sqlQuery, abortSignal);\n if (!validation.valid) {\n return {\n success: false,\n details: `SQL query failed: ${validation.error}. Please fix the sqlQuery and call this tool again.`,\n sqlQuery,\n vegaLiteSpec: null,\n };\n }\n }\n\n const parsedVegaLiteSpec = JSON.parse(vegaLiteSpec) as TopLevelSpec;\n\n let vegaWarnings: string[] = [];\n try {\n const compiled = compile(parsedVegaLiteSpec);\n vegaWarnings = (compiled as any).warnings ?? [];\n vegaParse(compiled.spec);\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n return {\n success: false,\n details: `Invalid Vega-Lite spec: ${message}`,\n sqlQuery: '',\n vegaLiteSpec: null,\n };\n }\n\n return {\n success: true,\n details:\n vegaWarnings.length > 0\n ? `Chart created successfully with warnings:\\n- ${vegaWarnings.join('\\n- ')}`\n : 'Chart created successfully.',\n sqlQuery,\n vegaLiteSpec: parsedVegaLiteSpec,\n };\n } catch (error) {\n return {\n success: false,\n details: `Not a valid JSON object: ${error}`,\n error: error instanceof Error ? error.message : String(error),\n sqlQuery: '',\n vegaLiteSpec: null,\n };\n }\n },\n toModelOutput: ({output}) => ({\n type: 'text',\n value: JSON.stringify({\n success: output.success,\n details: output.details,\n ...(output.error ? {error: output.error} : {}),\n }),\n }),\n });\n}\n"]}
|
|
@@ -1,32 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ToolRendererProps } from '@sqlrooms/ai';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { EmbedOptions } from 'vega-embed';
|
|
2
4
|
import { EditorMode } from './editor/types';
|
|
3
|
-
|
|
5
|
+
import type { VegaChartToolOutput, VegaChartToolParameters } from './VegaChartTool';
|
|
6
|
+
export type VegaChartToolResultProps = ToolRendererProps<VegaChartToolOutput, VegaChartToolParameters> & {
|
|
4
7
|
className?: string;
|
|
5
|
-
reasoning: string;
|
|
6
|
-
sqlQuery: string;
|
|
7
|
-
vegaLiteSpec: VisualizationSpec;
|
|
8
8
|
options?: EmbedOptions;
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
*/
|
|
12
|
-
toolCallId?: string;
|
|
13
|
-
/**
|
|
14
|
-
* Whether editing is enabled
|
|
15
|
-
* @default true
|
|
16
|
-
*/
|
|
17
|
-
editable?: boolean;
|
|
18
|
-
/**
|
|
19
|
-
* Which editors to show when editing
|
|
10
|
+
* Which editors to show when viewing
|
|
20
11
|
* @default 'both'
|
|
21
12
|
*/
|
|
22
13
|
editorMode?: EditorMode;
|
|
23
14
|
};
|
|
24
15
|
/**
|
|
25
16
|
* Renders a chart tool call with visualization using Vega-Lite.
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
* @param {VegaChartToolResultProps} props - The component props
|
|
29
|
-
* @returns {JSX.Element} The rendered chart tool call
|
|
17
|
+
* Shows read-only editors for inspecting spec and SQL.
|
|
30
18
|
*/
|
|
31
|
-
export declare function VegaChartToolResult({ className,
|
|
19
|
+
export declare function VegaChartToolResult({ className, output, options, editorMode, }: VegaChartToolResultProps): ReactNode;
|
|
32
20
|
//# sourceMappingURL=VegaChartToolResult.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VegaChartToolResult.d.ts","sourceRoot":"","sources":["../src/VegaChartToolResult.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"VegaChartToolResult.d.ts","sourceRoot":"","sources":["../src/VegaChartToolResult.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,cAAc,CAAC;AAEpD,OAAO,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AAChC,OAAO,EAAC,YAAY,EAAoB,MAAM,YAAY,CAAC;AAG3D,OAAO,EAAC,UAAU,EAAC,MAAM,gBAAgB,CAAC;AAC1C,OAAO,KAAK,EACV,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,iBAAiB,CAAC;AAKzB,MAAM,MAAM,wBAAwB,GAAG,iBAAiB,CACtD,mBAAmB,EACnB,uBAAuB,CACxB,GAAG;IACF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,SAAS,EACT,MAAM,EACN,OAAO,EACP,UAAmB,GACpB,EAAE,wBAAwB,GAAG,SAAS,CA2BtC"}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useStoreWithAi } from '@sqlrooms/ai';
|
|
3
2
|
import { cn } from '@sqlrooms/ui';
|
|
4
|
-
import { useCallback, useState } from 'react';
|
|
5
3
|
import { VegaChartContainer } from './editor/VegaChartContainer';
|
|
6
4
|
import { VegaChartDisplay } from './editor/VegaChartDisplay';
|
|
7
5
|
import { VegaEditAction } from './VegaEditAction';
|
|
@@ -9,38 +7,14 @@ import { VegaExportAction } from './VegaExportAction';
|
|
|
9
7
|
import { VegaLiteArrowChart } from './VegaLiteArrowChart';
|
|
10
8
|
/**
|
|
11
9
|
* Renders a chart tool call with visualization using Vega-Lite.
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* @param {VegaChartToolResultProps} props - The component props
|
|
15
|
-
* @returns {JSX.Element} The rendered chart tool call
|
|
10
|
+
* Shows read-only editors for inspecting spec and SQL.
|
|
16
11
|
*/
|
|
17
|
-
export function VegaChartToolResult({ className,
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const [appliedSql, setAppliedSql] = useState(sqlQuery);
|
|
25
|
-
// Callbacks to persist changes to AI slice
|
|
26
|
-
const handleSpecChange = useCallback((newSpec) => {
|
|
27
|
-
setAppliedSpec(newSpec);
|
|
28
|
-
if (toolCallId && currentSessionId) {
|
|
29
|
-
setToolAdditionalData(currentSessionId, toolCallId, {
|
|
30
|
-
sqlQuery: appliedSql,
|
|
31
|
-
vegaLiteSpec: newSpec,
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
}, [toolCallId, currentSessionId, appliedSql, setToolAdditionalData]);
|
|
35
|
-
const handleSqlChange = useCallback((newSql) => {
|
|
36
|
-
setAppliedSql(newSql);
|
|
37
|
-
if (toolCallId && currentSessionId) {
|
|
38
|
-
setToolAdditionalData(currentSessionId, toolCallId, {
|
|
39
|
-
sqlQuery: newSql,
|
|
40
|
-
vegaLiteSpec: appliedSpec,
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}, [toolCallId, currentSessionId, appliedSpec, setToolAdditionalData]);
|
|
44
|
-
return (_jsx("div", { className: cn('flex max-w-full flex-col gap-2', className), children: _jsx(VegaChartContainer, { spec: vegaLiteSpec, sqlQuery: sqlQuery, options: options, editable: editable, onSpecChange: handleSpecChange, onSqlChange: handleSqlChange, children: _jsx("div", { className: "relative max-w-full overflow-x-auto", children: _jsx(VegaChartDisplay, { aspectRatio: 16 / 9, className: "pt-2", children: _jsxs(VegaLiteArrowChart.Actions, { className: "right-3", children: [_jsx(VegaExportAction, {}), editable && _jsx(VegaEditAction, { editorMode: editorMode })] }) }) }) }) }));
|
|
12
|
+
export function VegaChartToolResult({ className, output, options, editorMode = 'both', }) {
|
|
13
|
+
const sqlQuery = output?.sqlQuery ?? '';
|
|
14
|
+
const vegaLiteSpec = output?.vegaLiteSpec;
|
|
15
|
+
if (!vegaLiteSpec) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
return (_jsx("div", { className: cn('flex max-w-full flex-col gap-2', className), children: _jsx(VegaChartContainer, { spec: vegaLiteSpec, sqlQuery: sqlQuery, options: options, editable: false, children: _jsx("div", { className: "relative max-w-full overflow-x-auto", children: _jsx(VegaChartDisplay, { aspectRatio: 16 / 9, className: "pt-2", children: _jsxs(VegaLiteArrowChart.Actions, { className: "right-3", children: [_jsx(VegaExportAction, {}), _jsx(VegaEditAction, { editorMode: editorMode })] }) }) }) }) }));
|
|
45
19
|
}
|
|
46
20
|
//# sourceMappingURL=VegaChartToolResult.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VegaChartToolResult.js","sourceRoot":"","sources":["../src/VegaChartToolResult.tsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"VegaChartToolResult.js","sourceRoot":"","sources":["../src/VegaChartToolResult.tsx"],"names":[],"mappings":";AACA,OAAO,EAAC,EAAE,EAAC,MAAM,cAAc,CAAC;AAGhC,OAAO,EAAC,kBAAkB,EAAC,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAC,gBAAgB,EAAC,MAAM,2BAA2B,CAAC;AAM3D,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAC,kBAAkB,EAAC,MAAM,sBAAsB,CAAC;AAexD;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAClC,SAAS,EACT,MAAM,EACN,OAAO,EACP,UAAU,GAAG,MAAM,GACM;IACzB,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,IAAI,EAAE,CAAC;IACxC,MAAM,YAAY,GAAG,MAAM,EAAE,YAAwC,CAAC;IAEtE,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,CACL,cAAK,SAAS,EAAE,EAAE,CAAC,gCAAgC,EAAE,SAAS,CAAC,YAC7D,KAAC,kBAAkB,IACjB,IAAI,EAAE,YAAY,EAClB,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,KAAK,YAEf,cAAK,SAAS,EAAC,qCAAqC,YAClD,KAAC,gBAAgB,IAAC,WAAW,EAAE,EAAE,GAAG,CAAC,EAAE,SAAS,EAAC,MAAM,YACrD,MAAC,kBAAkB,CAAC,OAAO,IAAC,SAAS,EAAC,SAAS,aAC7C,KAAC,gBAAgB,KAAG,EACpB,KAAC,cAAc,IAAC,UAAU,EAAE,UAAU,GAAI,IACf,GACZ,GACf,GACa,GACjB,CACP,CAAC;AACJ,CAAC","sourcesContent":["import type {ToolRendererProps} from '@sqlrooms/ai';\nimport {cn} from '@sqlrooms/ui';\nimport {ReactNode} from 'react';\nimport {EmbedOptions, VisualizationSpec} from 'vega-embed';\nimport {VegaChartContainer} from './editor/VegaChartContainer';\nimport {VegaChartDisplay} from './editor/VegaChartDisplay';\nimport {EditorMode} from './editor/types';\nimport type {\n VegaChartToolOutput,\n VegaChartToolParameters,\n} from './VegaChartTool';\nimport {VegaEditAction} from './VegaEditAction';\nimport {VegaExportAction} from './VegaExportAction';\nimport {VegaLiteArrowChart} from './VegaLiteArrowChart';\n\nexport type VegaChartToolResultProps = ToolRendererProps<\n VegaChartToolOutput,\n VegaChartToolParameters\n> & {\n className?: string;\n options?: EmbedOptions;\n /**\n * Which editors to show when viewing\n * @default 'both'\n */\n editorMode?: EditorMode;\n};\n\n/**\n * Renders a chart tool call with visualization using Vega-Lite.\n * Shows read-only editors for inspecting spec and SQL.\n */\nexport function VegaChartToolResult({\n className,\n output,\n options,\n editorMode = 'both',\n}: VegaChartToolResultProps): ReactNode {\n const sqlQuery = output?.sqlQuery ?? '';\n const vegaLiteSpec = output?.vegaLiteSpec as VisualizationSpec | null;\n\n if (!vegaLiteSpec) {\n return null;\n }\n\n return (\n <div className={cn('flex max-w-full flex-col gap-2', className)}>\n <VegaChartContainer\n spec={vegaLiteSpec}\n sqlQuery={sqlQuery}\n options={options}\n editable={false}\n >\n <div className=\"relative max-w-full overflow-x-auto\">\n <VegaChartDisplay aspectRatio={16 / 9} className=\"pt-2\">\n <VegaLiteArrowChart.Actions className=\"right-3\">\n <VegaExportAction />\n <VegaEditAction editorMode={editorMode} />\n </VegaLiteArrowChart.Actions>\n </VegaChartDisplay>\n </div>\n </VegaChartContainer>\n </div>\n );\n}\n"]}
|
package/dist/VegaEditAction.d.ts
CHANGED
|
@@ -11,14 +11,15 @@ export interface VegaEditActionProps {
|
|
|
11
11
|
className?: string;
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
|
-
* Edit action component for VegaLiteArrowChart.
|
|
15
|
-
* Provides a popover with tabbed Vega-Lite spec and SQL
|
|
14
|
+
* View/Edit action component for VegaLiteArrowChart.
|
|
15
|
+
* Provides a popover with tabbed Vega-Lite spec and SQL viewers.
|
|
16
|
+
* When `editable` is true in the context, shows editing controls.
|
|
16
17
|
*
|
|
17
18
|
* Must be used within a VegaChartContainer to access editor context.
|
|
18
19
|
*
|
|
19
20
|
* @example
|
|
20
21
|
* ```tsx
|
|
21
|
-
* <VegaChartContainer spec={spec} sqlQuery={query}
|
|
22
|
+
* <VegaChartContainer spec={spec} sqlQuery={query}>
|
|
22
23
|
* <VegaChartDisplay>
|
|
23
24
|
* <VegaLiteArrowChart.Actions>
|
|
24
25
|
* <VegaExportAction />
|
|
@@ -27,12 +28,6 @@ export interface VegaEditActionProps {
|
|
|
27
28
|
* </VegaChartDisplay>
|
|
28
29
|
* </VegaChartContainer>
|
|
29
30
|
* ```
|
|
30
|
-
*
|
|
31
|
-
* @example
|
|
32
|
-
* ```tsx
|
|
33
|
-
* // Spec editor only
|
|
34
|
-
* <VegaEditAction editorMode="spec" />
|
|
35
|
-
* ```
|
|
36
31
|
*/
|
|
37
32
|
export declare const VegaEditAction: React.FC<VegaEditActionProps>;
|
|
38
33
|
//# sourceMappingURL=VegaEditAction.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VegaEditAction.d.ts","sourceRoot":"","sources":["../src/VegaEditAction.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAC,UAAU,EAAC,MAAM,gBAAgB,CAAC;AAE1C,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"VegaEditAction.d.ts","sourceRoot":"","sources":["../src/VegaEditAction.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAC,UAAU,EAAC,MAAM,gBAAgB,CAAC;AAE1C,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAuCD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAoFxD,CAAC"}
|
package/dist/VegaEditAction.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Button, cn, Popover, PopoverContent, PopoverTrigger, Tabs, TabsContent, TabsList, TabsTrigger, useDisclosure, } from '@sqlrooms/ui';
|
|
3
|
-
import { Check, Code2,
|
|
3
|
+
import { Check, Code2, CodeIcon, Database } from 'lucide-react';
|
|
4
4
|
import { useState } from 'react';
|
|
5
5
|
import { useVegaEditorContext } from './editor/VegaEditorContext';
|
|
6
6
|
import { VegaSpecEditorPanel } from './editor/VegaSpecEditorPanel';
|
|
7
7
|
import { VegaSqlEditorPanel } from './editor/VegaSqlEditorPanel';
|
|
8
8
|
/**
|
|
9
|
-
* Inline editor actions component (Discard + Apply)
|
|
9
|
+
* Inline editor actions component (Discard + Apply).
|
|
10
|
+
* Only shown when editing is enabled.
|
|
10
11
|
*/
|
|
11
12
|
function EditorActions({ onClose }) {
|
|
12
13
|
const { actions, canApply, hasChanges } = useVegaEditorContext();
|
|
@@ -18,14 +19,15 @@ function EditorActions({ onClose }) {
|
|
|
18
19
|
}, disabled: !canApply, title: "Apply changes", children: [_jsx(Check, { className: "mr-1 h-3 w-3" }), "Apply"] })] }));
|
|
19
20
|
}
|
|
20
21
|
/**
|
|
21
|
-
* Edit action component for VegaLiteArrowChart.
|
|
22
|
-
* Provides a popover with tabbed Vega-Lite spec and SQL
|
|
22
|
+
* View/Edit action component for VegaLiteArrowChart.
|
|
23
|
+
* Provides a popover with tabbed Vega-Lite spec and SQL viewers.
|
|
24
|
+
* When `editable` is true in the context, shows editing controls.
|
|
23
25
|
*
|
|
24
26
|
* Must be used within a VegaChartContainer to access editor context.
|
|
25
27
|
*
|
|
26
28
|
* @example
|
|
27
29
|
* ```tsx
|
|
28
|
-
* <VegaChartContainer spec={spec} sqlQuery={query}
|
|
30
|
+
* <VegaChartContainer spec={spec} sqlQuery={query}>
|
|
29
31
|
* <VegaChartDisplay>
|
|
30
32
|
* <VegaLiteArrowChart.Actions>
|
|
31
33
|
* <VegaExportAction />
|
|
@@ -34,19 +36,14 @@ function EditorActions({ onClose }) {
|
|
|
34
36
|
* </VegaChartDisplay>
|
|
35
37
|
* </VegaChartContainer>
|
|
36
38
|
* ```
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* ```tsx
|
|
40
|
-
* // Spec editor only
|
|
41
|
-
* <VegaEditAction editorMode="spec" />
|
|
42
|
-
* ```
|
|
43
39
|
*/
|
|
44
40
|
export const VegaEditAction = ({ editorMode = 'both', className, }) => {
|
|
45
41
|
const editorPopover = useDisclosure();
|
|
42
|
+
const { editable } = useVegaEditorContext();
|
|
46
43
|
const [activeTab, setActiveTab] = useState('spec');
|
|
47
44
|
const showSpecEditor = editorMode === 'spec' || editorMode === 'both';
|
|
48
45
|
const showSqlEditor = editorMode === 'sql' || editorMode === 'both';
|
|
49
46
|
const showTabs = showSpecEditor && showSqlEditor;
|
|
50
|
-
return (_jsxs(Popover, { open: editorPopover.isOpen, onOpenChange: editorPopover.onToggle, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(Button, { type: "button", variant: "ghost", size: "xs", className: cn(className), "aria-label":
|
|
47
|
+
return (_jsxs(Popover, { open: editorPopover.isOpen, onOpenChange: editorPopover.onToggle, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(Button, { type: "button", variant: "ghost", size: "xs", className: cn(className), "aria-label": editable ? 'Edit chart specification' : 'View chart specification', children: _jsx(CodeIcon, { className: "h-4 w-4" }) }) }), _jsx(PopoverContent, { align: "end", side: "bottom", className: "w-[400px] p-0", children: _jsxs("div", { className: "flex h-[400px] flex-col", children: [_jsx("div", { className: "flex items-center justify-between border-b px-2 py-1", children: showTabs ? (_jsx(Tabs, { value: activeTab, onValueChange: (v) => setActiveTab(v), className: "w-full", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs(TabsList, { className: "h-7", children: [_jsxs(TabsTrigger, { value: "spec", className: "h-6 px-2 text-xs", children: [_jsx(Code2, { className: "mr-1 h-3 w-3" }), "Spec"] }), _jsxs(TabsTrigger, { value: "sql", className: "h-6 px-2 text-xs", children: [_jsx(Database, { className: "mr-1 h-3 w-3" }), "SQL"] })] }), editable && (_jsx(EditorActions, { onClose: editorPopover.onClose }))] }) })) : (_jsxs("div", { className: "flex w-full items-center justify-between", children: [_jsx("span", { className: "text-sm font-medium", children: showSpecEditor ? 'Vega-Lite Spec' : 'SQL Query' }), editable && _jsx(EditorActions, { onClose: editorPopover.onClose })] })) }), _jsx("div", { className: "flex-1 overflow-hidden", children: showTabs ? (_jsxs(Tabs, { value: activeTab, className: "h-full", children: [_jsx(TabsContent, { value: "spec", className: "mt-0 h-full", children: _jsx(VegaSpecEditorPanel, { title: "", className: "h-full" }) }), _jsx(TabsContent, { value: "sql", className: "mt-0 h-full", children: _jsx(VegaSqlEditorPanel, { title: "", className: "h-full" }) })] })) : showSpecEditor ? (_jsx(VegaSpecEditorPanel, { title: "", className: "h-full" })) : (_jsx(VegaSqlEditorPanel, { title: "", className: "h-full" })) })] }) })] }));
|
|
51
48
|
};
|
|
52
49
|
//# sourceMappingURL=VegaEditAction.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VegaEditAction.js","sourceRoot":"","sources":["../src/VegaEditAction.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,MAAM,EACN,EAAE,EACF,OAAO,EACP,cAAc,EACd,cAAc,EACd,IAAI,EACJ,WAAW,EACX,QAAQ,EACR,WAAW,EACX,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAC,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAC,QAAQ,EAAC,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAC,oBAAoB,EAAC,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAC,mBAAmB,EAAC,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAC,kBAAkB,EAAC,MAAM,6BAA6B,CAAC;AAe/D
|
|
1
|
+
{"version":3,"file":"VegaEditAction.js","sourceRoot":"","sources":["../src/VegaEditAction.tsx"],"names":[],"mappings":"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","sourcesContent":["import {\n Button,\n cn,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Tabs,\n TabsContent,\n TabsList,\n TabsTrigger,\n useDisclosure,\n} from '@sqlrooms/ui';\nimport {Check, Code2, CodeIcon, Database} from 'lucide-react';\nimport {useState} from 'react';\nimport {useVegaEditorContext} from './editor/VegaEditorContext';\nimport {VegaSpecEditorPanel} from './editor/VegaSpecEditorPanel';\nimport {VegaSqlEditorPanel} from './editor/VegaSqlEditorPanel';\nimport {EditorMode} from './editor/types';\n\nexport interface VegaEditActionProps {\n /**\n * Which editors to show: 'spec', 'sql', or 'both'\n * @default 'both'\n */\n editorMode?: EditorMode;\n /**\n * Additional CSS classes for the trigger button\n */\n className?: string;\n}\n\n/**\n * Inline editor actions component (Discard + Apply).\n * Only shown when editing is enabled.\n */\nfunction EditorActions({onClose}: {onClose: () => void}) {\n const {actions, canApply, hasChanges} = useVegaEditorContext();\n\n return (\n <div className=\"flex items-center gap-1\">\n <Button\n variant=\"ghost\"\n size=\"xs\"\n onClick={() => {\n actions.cancelChanges();\n }}\n disabled={!hasChanges}\n title=\"Discard changes\"\n >\n Discard\n </Button>\n <Button\n variant=\"default\"\n size=\"xs\"\n onClick={() => {\n actions.applyChanges();\n onClose();\n }}\n disabled={!canApply}\n title=\"Apply changes\"\n >\n <Check className=\"mr-1 h-3 w-3\" />\n Apply\n </Button>\n </div>\n );\n}\n\n/**\n * View/Edit action component for VegaLiteArrowChart.\n * Provides a popover with tabbed Vega-Lite spec and SQL viewers.\n * When `editable` is true in the context, shows editing controls.\n *\n * Must be used within a VegaChartContainer to access editor context.\n *\n * @example\n * ```tsx\n * <VegaChartContainer spec={spec} sqlQuery={query}>\n * <VegaChartDisplay>\n * <VegaLiteArrowChart.Actions>\n * <VegaExportAction />\n * <VegaEditAction editorMode=\"both\" />\n * </VegaLiteArrowChart.Actions>\n * </VegaChartDisplay>\n * </VegaChartContainer>\n * ```\n */\nexport const VegaEditAction: React.FC<VegaEditActionProps> = ({\n editorMode = 'both',\n className,\n}) => {\n const editorPopover = useDisclosure();\n const {editable} = useVegaEditorContext();\n const [activeTab, setActiveTab] = useState<'spec' | 'sql'>('spec');\n\n const showSpecEditor = editorMode === 'spec' || editorMode === 'both';\n const showSqlEditor = editorMode === 'sql' || editorMode === 'both';\n const showTabs = showSpecEditor && showSqlEditor;\n\n return (\n <Popover open={editorPopover.isOpen} onOpenChange={editorPopover.onToggle}>\n <PopoverTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"xs\"\n className={cn(className)}\n aria-label={\n editable ? 'Edit chart specification' : 'View chart specification'\n }\n >\n <CodeIcon className=\"h-4 w-4\" />\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" side=\"bottom\" className=\"w-[400px] p-0\">\n <div className=\"flex h-[400px] flex-col\">\n {/* Header with tabs */}\n <div className=\"flex items-center justify-between border-b px-2 py-1\">\n {showTabs ? (\n <Tabs\n value={activeTab}\n onValueChange={(v) => setActiveTab(v as 'spec' | 'sql')}\n className=\"w-full\"\n >\n <div className=\"flex items-center justify-between\">\n <TabsList className=\"h-7\">\n <TabsTrigger value=\"spec\" className=\"h-6 px-2 text-xs\">\n <Code2 className=\"mr-1 h-3 w-3\" />\n Spec\n </TabsTrigger>\n <TabsTrigger value=\"sql\" className=\"h-6 px-2 text-xs\">\n <Database className=\"mr-1 h-3 w-3\" />\n SQL\n </TabsTrigger>\n </TabsList>\n {editable && (\n <EditorActions onClose={editorPopover.onClose} />\n )}\n </div>\n </Tabs>\n ) : (\n <div className=\"flex w-full items-center justify-between\">\n <span className=\"text-sm font-medium\">\n {showSpecEditor ? 'Vega-Lite Spec' : 'SQL Query'}\n </span>\n {editable && <EditorActions onClose={editorPopover.onClose} />}\n </div>\n )}\n </div>\n\n {/* Editor content */}\n <div className=\"flex-1 overflow-hidden\">\n {showTabs ? (\n <Tabs value={activeTab} className=\"h-full\">\n <TabsContent value=\"spec\" className=\"mt-0 h-full\">\n <VegaSpecEditorPanel title=\"\" className=\"h-full\" />\n </TabsContent>\n <TabsContent value=\"sql\" className=\"mt-0 h-full\">\n <VegaSqlEditorPanel title=\"\" className=\"h-full\" />\n </TabsContent>\n </Tabs>\n ) : showSpecEditor ? (\n <VegaSpecEditorPanel title=\"\" className=\"h-full\" />\n ) : (\n <VegaSqlEditorPanel title=\"\" className=\"h-full\" />\n )}\n </div>\n </div>\n </PopoverContent>\n </Popover>\n );\n};\n"]}
|