@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.
Files changed (43) hide show
  1. package/dist/VegaChartActions.js +1 -1
  2. package/dist/VegaChartActions.js.map +1 -1
  3. package/dist/VegaChartTool.d.ts +47 -26
  4. package/dist/VegaChartTool.d.ts.map +1 -1
  5. package/dist/VegaChartTool.js +61 -35
  6. package/dist/VegaChartTool.js.map +1 -1
  7. package/dist/VegaChartToolResult.d.ts +8 -20
  8. package/dist/VegaChartToolResult.d.ts.map +1 -1
  9. package/dist/VegaChartToolResult.js +8 -34
  10. package/dist/VegaChartToolResult.js.map +1 -1
  11. package/dist/VegaEditAction.d.ts +4 -9
  12. package/dist/VegaEditAction.d.ts.map +1 -1
  13. package/dist/VegaEditAction.js +9 -12
  14. package/dist/VegaEditAction.js.map +1 -1
  15. package/dist/VegaLiteArrowChart.d.ts.map +1 -1
  16. package/dist/VegaLiteArrowChart.js +1 -0
  17. package/dist/VegaLiteArrowChart.js.map +1 -1
  18. package/dist/VegaLiteChart.d.ts +44 -0
  19. package/dist/VegaLiteChart.d.ts.map +1 -0
  20. package/dist/VegaLiteChart.js +134 -0
  21. package/dist/VegaLiteChart.js.map +1 -0
  22. package/dist/VegaLiteSqlChart.js +1 -1
  23. package/dist/VegaLiteSqlChart.js.map +1 -1
  24. package/dist/editor/VegaCodeMirrorEditor.d.ts +15 -0
  25. package/dist/editor/VegaCodeMirrorEditor.d.ts.map +1 -0
  26. package/dist/editor/VegaCodeMirrorEditor.js +23 -0
  27. package/dist/editor/VegaCodeMirrorEditor.js.map +1 -0
  28. package/dist/editor/VegaMonacoEditor.d.ts +5 -0
  29. package/dist/editor/VegaMonacoEditor.d.ts.map +1 -1
  30. package/dist/editor/VegaMonacoEditor.js +2 -0
  31. package/dist/editor/VegaMonacoEditor.js.map +1 -1
  32. package/dist/editor/VegaSpecEditorPanel.d.ts.map +1 -1
  33. package/dist/editor/VegaSpecEditorPanel.js +11 -7
  34. package/dist/editor/VegaSpecEditorPanel.js.map +1 -1
  35. package/dist/editor/VegaSqlEditorPanel.d.ts +1 -1
  36. package/dist/editor/VegaSqlEditorPanel.d.ts.map +1 -1
  37. package/dist/editor/VegaSqlEditorPanel.js +9 -10
  38. package/dist/editor/VegaSqlEditorPanel.js.map +1 -1
  39. package/dist/index.d.ts +5 -2
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +3 -1
  42. package/dist/index.js.map +1 -1
  43. package/package.json +11 -10
@@ -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-coarse:pointer-events-auto pointer-coarse:opacity-100 pointer-events-none absolute right-0 top-1 z-10 flex items-center gap-1 opacity-0 transition-opacity focus-within:pointer-events-auto focus-within:opacity-100 hover:pointer-events-auto hover:opacity-100 peer-focus-within:pointer-events-auto peer-focus-within:opacity-100 peer-hover:pointer-events-auto peer-hover:opacity-100', className), children: children }));
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-coarse:pointer-events-auto pointer-coarse:opacity-100 pointer-events-none absolute right-0 top-1 z-10 flex items-center gap-1 opacity-0 transition-opacity focus-within:pointer-events-auto focus-within:opacity-100 hover:pointer-events-auto hover:opacity-100 peer-focus-within:pointer-events-auto peer-focus-within:opacity-100 peer-hover:pointer-events-auto peer-hover:opacity-100',\n className,\n )}\n >\n {children}\n </div>\n );\n};\n"]}
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"]}
@@ -1,7 +1,11 @@
1
1
  import { z } from 'zod';
2
- import type { OpenAssistantTool } from '@openassistant/utils';
3
- import { EmbedOptions } from 'vega-embed';
4
- import { EditorMode } from './editor/types';
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 VegaChartToolArgs = z.ZodObject<{
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: object;
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
- * Vega embed options
42
- */
43
- embedOptions?: EmbedOptions;
44
- /**
45
- * Whether editing is enabled
46
- * @default true
47
- */
48
- editable?: boolean;
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
- editorMode?: EditorMode;
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, embedOptions, editable, editorMode, }?: VegaChartToolOptions): OpenAssistantTool<typeof VegaChartToolParameters, VegaChartToolLlmResult, VegaChartToolAdditionalData, VegaChartToolContext>;
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":"AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAKtB,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,sBAAsB,CAAC;AAG5D,OAAO,EAAC,YAAY,EAAC,MAAM,YAAY,CAAC;AAExC,OAAO,EAAC,UAAU,EAAC,MAAM,gBAAgB,CAAC;AAE1C;;GAEG;AACH,eAAO,MAAM,uBAAuB;;;;iBAIlC,CAAC;AAEH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAE9E,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,SAAS,CAAC;IAC1C,QAAQ,EAAE,CAAC,CAAC,SAAS,CAAC;IACtB,YAAY,EAAE,CAAC,CAAC,SAAS,CAAC;IAC1B,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC;CACxB,CAAC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,2BAA2B,GAAG;IACxC,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC;AAE3C;;GAEG;AACH,eAAO,MAAM,8BAA8B,smCAY4I,CAAC;AAExL;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,WAA4C,EAC5C,YAA2C,EAC3C,QAAe,EACf,UAAmB,GACpB,GAAE,oBAAyB,GAAG,iBAAiB,CAC9C,OAAO,uBAAuB,EAC9B,sBAAsB,EACtB,2BAA2B,EAC3B,oBAAoB,CACrB,CAwEA"}
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"}
@@ -1,9 +1,29 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
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
- import { makeDefaultVegaLiteOptions } from './VegaLiteArrowChart';
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, embedOptions = makeDefaultVegaLiteOptions(), editable = true, editorMode = 'both', } = {}) {
40
- return {
41
- name: 'chart',
59
+ export function createVegaChartTool({ description = DEFAULT_VEGA_CHART_DESCRIPTION, validateSql, } = {}) {
60
+ return tool({
42
61
  description,
43
- parameters: VegaChartToolParameters,
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
- llmResult: {
68
- success: false,
69
- details: `Invalid Vega-Lite spec: ${message}`,
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
- llmResult: {
77
- success: true,
78
- details: vegaWarnings.length > 0
79
- ? `Chart created successfully with warnings:\n- ${vegaWarnings.join('\n- ')}`
80
- : 'Chart created successfully.',
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
- llmResult: {
91
- success: false,
92
- details: `Not a valid JSON object: ${error}`,
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
- component: ({ options, ...restProps }) => (_jsx(VegaChartToolResult, { ...restProps, options: { ...options, ...embedOptions }, editable: editable, editorMode: editorMode })),
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":";AAAA,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,EACL,mBAAmB,GAEpB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAC,OAAO,EAAe,MAAM,WAAW,CAAC;AAChD,OAAO,EAAC,KAAK,IAAI,SAAS,EAAC,MAAM,MAAM,CAAC;AAExC,OAAO,EAAC,0BAA0B,EAAC,MAAM,sBAAsB,CAAC;AAGhE;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC9C,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE;IACpB,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE;IACxB,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE;CACtB,CAAC,CAAC;AAsBH;;GAEG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG;;;;;;;;;;;;uLAYyI,CAAC;AA0BxL;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAClC,WAAW,GAAG,8BAA8B,EAC5C,YAAY,GAAG,0BAA0B,EAAE,EAC3C,QAAQ,GAAG,IAAI,EACf,UAAU,GAAG,MAAM,MACK,EAAE;IAM1B,OAAO;QACL,IAAI,EAAE,OAAO;QACb,WAAW;QACX,UAAU,EAAE,uBAAuB;QACnC,OAAO,EAAE,KAAK,EACZ,MAA+B,EAC/B,OAAqC,EACrC,EAAE;YACF,MAAM,WAAW,GAAG,OAAO,EAAE,WAAW,CAAC;YACzC,MAAM,EAAC,QAAQ,EAAE,YAAY,EAAC,GAAG,MAAM,CAAC;YACxC,IAAI,CAAC;gBACH,mCAAmC;gBACnC,IAAI,WAAW,EAAE,OAAO,EAAE,CAAC;oBACzB,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;gBAChD,CAAC;gBAED,MAAM,kBAAkB,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAiB,CAAC;gBAEpE,uEAAuE;gBACvE,mDAAmD;gBACnD,gEAAgE;gBAChE,IAAI,YAAY,GAAa,EAAE,CAAC;gBAChC,IAAI,CAAC;oBACH,MAAM,QAAQ,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;oBAC7C,mFAAmF;oBACnF,YAAY,GAAI,QAAgB,CAAC,QAAQ,IAAI,EAAE,CAAC;oBAChD,uDAAuD;oBACvD,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBAC3B,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACX,MAAM,OAAO,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;oBAC3D,OAAO;wBACL,SAAS,EAAE;4BACT,OAAO,EAAE,KAAK;4BACd,OAAO,EAAE,2BAA2B,OAAO,EAAE;yBAC9C;qBACF,CAAC;gBACJ,CAAC;gBAED,+CAA+C;gBAC/C,+HAA+H;gBAC/H,OAAO;oBACL,SAAS,EAAE;wBACT,OAAO,EAAE,IAAI;wBACb,OAAO,EACL,YAAY,CAAC,MAAM,GAAG,CAAC;4BACrB,CAAC,CAAC,gDAAgD,YAAY,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;4BAC7E,CAAC,CAAC,6BAA6B;qBACpC;oBACD,cAAc,EAAE;wBACd,QAAQ;wBACR,YAAY,EAAE,kBAAkB;qBACjC;iBACF,CAAC;YACJ,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO;oBACL,SAAS,EAAE;wBACT,OAAO,EAAE,KAAK;wBACd,OAAO,EAAE,4BAA4B,KAAK,EAAE;qBAC7C;iBACF,CAAC;YACJ,CAAC;QACH,CAAC;QACD,SAAS,EAAE,CAAC,EAAC,OAAO,EAAE,GAAG,SAAS,EAA2B,EAAE,EAAE,CAAC,CAChE,KAAC,mBAAmB,OACd,SAAS,EACb,OAAO,EAAE,EAAC,GAAG,OAAO,EAAE,GAAG,YAAY,EAAC,EACtC,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAE,UAAU,GACtB,CACH;KACF,CAAC;AACJ,CAAC","sourcesContent":["import {z} from 'zod';\nimport {\n VegaChartToolResult,\n VegaChartToolResultProps,\n} from './VegaChartToolResult';\nimport type {OpenAssistantTool} from '@openassistant/utils';\nimport {compile, TopLevelSpec} from 'vega-lite';\nimport {parse as vegaParse} from 'vega';\nimport {EmbedOptions} from 'vega-embed';\nimport {makeDefaultVegaLiteOptions} from './VegaLiteArrowChart';\nimport {EditorMode} from './editor/types';\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 VegaChartToolArgs = z.ZodObject<{\n sqlQuery: z.ZodString;\n vegaLiteSpec: z.ZodString;\n reasoning: z.ZodString;\n}>;\n\nexport type VegaChartToolLlmResult = {\n success: boolean;\n details: string;\n};\n\nexport type VegaChartToolAdditionalData = {\n sqlQuery: string;\n vegaLiteSpec: object;\n};\n\nexport type VegaChartToolContext = unknown;\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 * Vega embed options\n */\n embedOptions?: EmbedOptions;\n /**\n * Whether editing is enabled\n * @default true\n */\n editable?: boolean;\n /**\n * Which editors to show when editing\n * @default 'both'\n */\n editorMode?: EditorMode;\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 embedOptions = makeDefaultVegaLiteOptions(),\n editable = true,\n editorMode = 'both',\n}: VegaChartToolOptions = {}): OpenAssistantTool<\n typeof VegaChartToolParameters,\n VegaChartToolLlmResult,\n VegaChartToolAdditionalData,\n VegaChartToolContext\n> {\n return {\n name: 'chart',\n description,\n parameters: VegaChartToolParameters,\n execute: async (\n params: VegaChartToolParameters,\n options?: {abortSignal?: AbortSignal},\n ) => {\n const abortSignal = options?.abortSignal;\n const {sqlQuery, vegaLiteSpec} = params;\n try {\n // Check if aborted before starting\n if (abortSignal?.aborted) {\n throw new Error('Chart creation was aborted');\n }\n\n const parsedVegaLiteSpec = JSON.parse(vegaLiteSpec) as TopLevelSpec;\n\n // Validate/spec-check by compiling to Vega and attempting to parse it.\n // - compile() can throw on invalid Vega-Lite specs\n // - vegaParse() will throw if the compiled Vega spec is invalid\n let vegaWarnings: string[] = [];\n try {\n const compiled = compile(parsedVegaLiteSpec);\n // vega-lite's compile() may expose warnings at runtime, but types don't include it\n vegaWarnings = (compiled as any).warnings ?? [];\n // This will throw if the compiled Vega spec is invalid\n vegaParse(compiled.spec);\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n return {\n llmResult: {\n success: false,\n details: `Invalid Vega-Lite spec: ${message}`,\n },\n };\n }\n\n // data object of the vegaLiteSpec and sqlQuery\n // 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\n return {\n llmResult: {\n success: true,\n details:\n vegaWarnings.length > 0\n ? `Chart created successfully with warnings:\\n- ${vegaWarnings.join('\\n- ')}`\n : 'Chart created successfully.',\n },\n additionalData: {\n sqlQuery,\n vegaLiteSpec: parsedVegaLiteSpec,\n },\n };\n } catch (error) {\n return {\n llmResult: {\n success: false,\n details: `Not a valid JSON object: ${error}`,\n },\n };\n }\n },\n component: ({options, ...restProps}: VegaChartToolResultProps) => (\n <VegaChartToolResult\n {...restProps}\n options={{...options, ...embedOptions}}\n editable={editable}\n editorMode={editorMode}\n />\n ),\n };\n}\n"]}
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 { EmbedOptions, VisualizationSpec } from 'vega-embed';
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
- export type VegaChartToolResultProps = {
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
- * Tool call ID for AI slice integration (enables persistence)
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
- * Supports inline editing with AI slice persistence.
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, sqlQuery, vegaLiteSpec, options, toolCallId, editable, editorMode, }: VegaChartToolResultProps): import("react/jsx-runtime").JSX.Element;
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":"AAGA,OAAO,EAAC,YAAY,EAAE,iBAAiB,EAAC,MAAM,YAAY,CAAC;AAG3D,OAAO,EAAC,UAAU,EAAC,MAAM,gBAAgB,CAAC;AAK1C,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,iBAAiB,CAAC;IAChC,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,UAAU,EACV,QAAe,EACf,UAAmB,GACpB,EAAE,wBAAwB,2CA6D1B"}
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
- * Supports inline editing with AI slice persistence.
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, sqlQuery, vegaLiteSpec, options, toolCallId, editable = true, editorMode = 'both', }) {
18
- // AI slice integration for persisting changes
19
- const setToolAdditionalData = useStoreWithAi((s) => s.ai.setSessionToolAdditionalData);
20
- const currentSession = useStoreWithAi((s) => s.ai.getCurrentSession());
21
- const currentSessionId = currentSession?.id;
22
- // Track applied values for callbacks (to persist both spec and sql together)
23
- const [appliedSpec, setAppliedSpec] = useState(vegaLiteSpec);
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":";AAAA,OAAO,EAAC,cAAc,EAAC,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAC,EAAE,EAAC,MAAM,cAAc,CAAC;AAChC,OAAO,EAAC,WAAW,EAAE,QAAQ,EAAC,MAAM,OAAO,CAAC;AAE5C,OAAO,EAAC,kBAAkB,EAAC,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAC,gBAAgB,EAAC,MAAM,2BAA2B,CAAC;AAE3D,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAC,kBAAkB,EAAC,MAAM,sBAAsB,CAAC;AAwBxD;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAClC,SAAS,EACT,QAAQ,EACR,YAAY,EACZ,OAAO,EACP,UAAU,EACV,QAAQ,GAAG,IAAI,EACf,UAAU,GAAG,MAAM,GACM;IACzB,8CAA8C;IAC9C,MAAM,qBAAqB,GAAG,cAAc,CAC1C,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,4BAA4B,CACzC,CAAC;IACF,MAAM,cAAc,GAAG,cAAc,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,CAAC;IACvE,MAAM,gBAAgB,GAAG,cAAc,EAAE,EAAE,CAAC;IAE5C,6EAA6E;IAC7E,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC7D,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAEvD,2CAA2C;IAC3C,MAAM,gBAAgB,GAAG,WAAW,CAClC,CAAC,OAA0B,EAAE,EAAE;QAC7B,cAAc,CAAC,OAAO,CAAC,CAAC;QACxB,IAAI,UAAU,IAAI,gBAAgB,EAAE,CAAC;YACnC,qBAAqB,CAAC,gBAAgB,EAAE,UAAU,EAAE;gBAClD,QAAQ,EAAE,UAAU;gBACpB,YAAY,EAAE,OAAO;aACtB,CAAC,CAAC;QACL,CAAC;IACH,CAAC,EACD,CAAC,UAAU,EAAE,gBAAgB,EAAE,UAAU,EAAE,qBAAqB,CAAC,CAClE,CAAC;IAEF,MAAM,eAAe,GAAG,WAAW,CACjC,CAAC,MAAc,EAAE,EAAE;QACjB,aAAa,CAAC,MAAM,CAAC,CAAC;QACtB,IAAI,UAAU,IAAI,gBAAgB,EAAE,CAAC;YACnC,qBAAqB,CAAC,gBAAgB,EAAE,UAAU,EAAE;gBAClD,QAAQ,EAAE,MAAM;gBAChB,YAAY,EAAE,WAAW;aAC1B,CAAC,CAAC;QACL,CAAC;IACH,CAAC,EACD,CAAC,UAAU,EAAE,gBAAgB,EAAE,WAAW,EAAE,qBAAqB,CAAC,CACnE,CAAC;IAEF,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,QAAQ,EAClB,YAAY,EAAE,gBAAgB,EAC9B,WAAW,EAAE,eAAe,YAG5B,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,EACnB,QAAQ,IAAI,KAAC,cAAc,IAAC,UAAU,EAAE,UAAU,GAAI,IAC5B,GACZ,GACf,GACa,GACjB,CACP,CAAC;AACJ,CAAC","sourcesContent":["import {useStoreWithAi} from '@sqlrooms/ai';\nimport {cn} from '@sqlrooms/ui';\nimport {useCallback, useState} from 'react';\nimport {EmbedOptions, VisualizationSpec} from 'vega-embed';\nimport {VegaChartContainer} from './editor/VegaChartContainer';\nimport {VegaChartDisplay} from './editor/VegaChartDisplay';\nimport {EditorMode} from './editor/types';\nimport {VegaEditAction} from './VegaEditAction';\nimport {VegaExportAction} from './VegaExportAction';\nimport {VegaLiteArrowChart} from './VegaLiteArrowChart';\n\nexport type VegaChartToolResultProps = {\n className?: string;\n reasoning: string;\n sqlQuery: string;\n vegaLiteSpec: VisualizationSpec;\n options?: EmbedOptions;\n /**\n * Tool call ID for AI slice integration (enables persistence)\n */\n toolCallId?: string;\n /**\n * Whether editing is enabled\n * @default true\n */\n editable?: boolean;\n /**\n * Which editors to show when editing\n * @default 'both'\n */\n editorMode?: EditorMode;\n};\n\n/**\n * Renders a chart tool call with visualization using Vega-Lite.\n * Supports inline editing with AI slice persistence.\n *\n * @param {VegaChartToolResultProps} props - The component props\n * @returns {JSX.Element} The rendered chart tool call\n */\nexport function VegaChartToolResult({\n className,\n sqlQuery,\n vegaLiteSpec,\n options,\n toolCallId,\n editable = true,\n editorMode = 'both',\n}: VegaChartToolResultProps) {\n // AI slice integration for persisting changes\n const setToolAdditionalData = useStoreWithAi(\n (s) => s.ai.setSessionToolAdditionalData,\n );\n const currentSession = useStoreWithAi((s) => s.ai.getCurrentSession());\n const currentSessionId = currentSession?.id;\n\n // Track applied values for callbacks (to persist both spec and sql together)\n const [appliedSpec, setAppliedSpec] = useState(vegaLiteSpec);\n const [appliedSql, setAppliedSql] = useState(sqlQuery);\n\n // Callbacks to persist changes to AI slice\n const handleSpecChange = useCallback(\n (newSpec: VisualizationSpec) => {\n setAppliedSpec(newSpec);\n if (toolCallId && currentSessionId) {\n setToolAdditionalData(currentSessionId, toolCallId, {\n sqlQuery: appliedSql,\n vegaLiteSpec: newSpec,\n });\n }\n },\n [toolCallId, currentSessionId, appliedSql, setToolAdditionalData],\n );\n\n const handleSqlChange = useCallback(\n (newSql: string) => {\n setAppliedSql(newSql);\n if (toolCallId && currentSessionId) {\n setToolAdditionalData(currentSessionId, toolCallId, {\n sqlQuery: newSql,\n vegaLiteSpec: appliedSpec,\n });\n }\n },\n [toolCallId, currentSessionId, appliedSpec, setToolAdditionalData],\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={editable}\n onSpecChange={handleSpecChange}\n onSqlChange={handleSqlChange}\n >\n {/* Chart with actions toolbar */}\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 {editable && <VegaEditAction editorMode={editorMode} />}\n </VegaLiteArrowChart.Actions>\n </VegaChartDisplay>\n </div>\n </VegaChartContainer>\n </div>\n );\n}\n"]}
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"]}
@@ -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 editors.
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} editable>
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;AAsCD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CA+ExD,CAAC"}
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"}
@@ -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, Database, EditIcon } from 'lucide-react';
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 editors.
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} editable>
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": "Edit chart specification", children: _jsx(EditIcon, { 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"] })] }), _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' }), _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" })) })] }) })] }));
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":"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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, Database, EditIcon} 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 */\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 * Edit action component for VegaLiteArrowChart.\n * Provides a popover with tabbed Vega-Lite spec and SQL editors.\n *\n * Must be used within a VegaChartContainer to access editor context.\n *\n * @example\n * ```tsx\n * <VegaChartContainer spec={spec} sqlQuery={query} editable>\n * <VegaChartDisplay>\n * <VegaLiteArrowChart.Actions>\n * <VegaExportAction />\n * <VegaEditAction editorMode=\"both\" />\n * </VegaLiteArrowChart.Actions>\n * </VegaChartDisplay>\n * </VegaChartContainer>\n * ```\n *\n * @example\n * ```tsx\n * // Spec editor only\n * <VegaEditAction editorMode=\"spec\" />\n * ```\n */\nexport const VegaEditAction: React.FC<VegaEditActionProps> = ({\n editorMode = 'both',\n className,\n}) => {\n const editorPopover = useDisclosure();\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=\"Edit chart specification\"\n >\n <EditIcon 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 <EditorActions onClose={editorPopover.onClose} />\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 <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"]}
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"]}