@prismiq/react 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/{CustomSQLEditor-DYeId0Gp.d.ts → ChatBubble-ARocmvZD.d.cts} +48 -4
  2. package/dist/{CustomSQLEditor-BXB4rf1q.d.cts → ChatBubble-BN_CjIpk.d.ts} +48 -4
  3. package/dist/{DashboardDialog-B3vYC5Gs.d.ts → DashboardDialog-UhUGXx2h.d.ts} +6 -4
  4. package/dist/{DashboardDialog-LHmrtNQU.d.cts → DashboardDialog-Z-HypxmG.d.cts} +6 -4
  5. package/dist/{accessibility-2yy5yqRR.d.cts → accessibility-Bu2mNtaB.d.cts} +1 -1
  6. package/dist/{accessibility-2yy5yqRR.d.ts → accessibility-Bu2mNtaB.d.ts} +1 -1
  7. package/dist/charts/index.cjs +27 -27
  8. package/dist/charts/index.d.cts +2 -2
  9. package/dist/charts/index.d.ts +2 -2
  10. package/dist/charts/index.js +2 -2
  11. package/dist/{chunk-NK7HKX2J.cjs → chunk-73TPDGXB.cjs} +7 -7
  12. package/dist/{chunk-NK7HKX2J.cjs.map → chunk-73TPDGXB.cjs.map} +1 -1
  13. package/dist/{chunk-FEABEF3J.cjs → chunk-FKXCINUF.cjs} +551 -299
  14. package/dist/chunk-FKXCINUF.cjs.map +1 -0
  15. package/dist/{chunk-2H5WTH4K.js → chunk-FQ23KG6G.js} +3 -3
  16. package/dist/{chunk-2H5WTH4K.js.map → chunk-FQ23KG6G.js.map} +1 -1
  17. package/dist/{chunk-UPYINBZU.js → chunk-GELI7MDZ.js} +982 -51
  18. package/dist/chunk-GELI7MDZ.js.map +1 -0
  19. package/dist/{chunk-WWTT2OJ5.js → chunk-HKZFEXT6.js} +27 -9
  20. package/dist/chunk-HKZFEXT6.js.map +1 -0
  21. package/dist/{chunk-MOAEEF5P.js → chunk-JBJ5LEAG.js} +362 -110
  22. package/dist/chunk-JBJ5LEAG.js.map +1 -0
  23. package/dist/{chunk-4AVL6GQK.cjs → chunk-KXB2IZI2.cjs} +36 -9
  24. package/dist/chunk-KXB2IZI2.cjs.map +1 -0
  25. package/dist/{chunk-EX74SI67.js → chunk-LBE6GIBC.js} +36 -9
  26. package/dist/chunk-LBE6GIBC.js.map +1 -0
  27. package/dist/{chunk-NY6TZLST.cjs → chunk-PG7QBH3G.cjs} +988 -53
  28. package/dist/chunk-PG7QBH3G.cjs.map +1 -0
  29. package/dist/{chunk-MDXGGZSW.cjs → chunk-ZYVN6XAZ.cjs} +35 -37
  30. package/dist/chunk-ZYVN6XAZ.cjs.map +1 -0
  31. package/dist/components/index.cjs +63 -55
  32. package/dist/components/index.d.cts +2 -2
  33. package/dist/components/index.d.ts +2 -2
  34. package/dist/components/index.js +2 -2
  35. package/dist/dashboard/index.cjs +36 -36
  36. package/dist/dashboard/index.d.cts +7 -5
  37. package/dist/dashboard/index.d.ts +7 -5
  38. package/dist/dashboard/index.js +4 -4
  39. package/dist/export/index.cjs +7 -7
  40. package/dist/export/index.d.cts +6 -4
  41. package/dist/export/index.d.ts +6 -4
  42. package/dist/export/index.js +1 -1
  43. package/dist/{index-C-Qcuu4Y.d.cts → index-B8DelfpL.d.cts} +2 -2
  44. package/dist/{index-rPc7ijt8.d.ts → index-RbfYPQD_.d.ts} +2 -2
  45. package/dist/index.cjs +150 -134
  46. package/dist/index.cjs.map +1 -1
  47. package/dist/index.d.cts +97 -9
  48. package/dist/index.d.ts +97 -9
  49. package/dist/index.js +7 -7
  50. package/dist/index.js.map +1 -1
  51. package/dist/{types-WrCbOeAV.d.cts → types-ccB9Ps3k.d.cts} +59 -1
  52. package/dist/{types-WrCbOeAV.d.ts → types-ccB9Ps3k.d.ts} +59 -1
  53. package/dist/utils/index.cjs +15 -15
  54. package/dist/utils/index.d.cts +5 -21
  55. package/dist/utils/index.d.ts +5 -21
  56. package/dist/utils/index.js +1 -1
  57. package/package.json +3 -7
  58. package/dist/chunk-4AVL6GQK.cjs.map +0 -1
  59. package/dist/chunk-EX74SI67.js.map +0 -1
  60. package/dist/chunk-FEABEF3J.cjs.map +0 -1
  61. package/dist/chunk-MDXGGZSW.cjs.map +0 -1
  62. package/dist/chunk-MOAEEF5P.js.map +0 -1
  63. package/dist/chunk-NY6TZLST.cjs.map +0 -1
  64. package/dist/chunk-UPYINBZU.js.map +0 -1
  65. package/dist/chunk-WWTT2OJ5.js.map +0 -1
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var chunkNK7HKX2J_cjs = require('./chunk-NK7HKX2J.cjs');
4
- var chunkNY6TZLST_cjs = require('./chunk-NY6TZLST.cjs');
3
+ var chunk73TPDGXB_cjs = require('./chunk-73TPDGXB.cjs');
4
+ var chunkPG7QBH3G_cjs = require('./chunk-PG7QBH3G.cjs');
5
5
  var chunkLMTG3LRC_cjs = require('./chunk-LMTG3LRC.cjs');
6
- var chunk4AVL6GQK_cjs = require('./chunk-4AVL6GQK.cjs');
6
+ var chunkKXB2IZI2_cjs = require('./chunk-KXB2IZI2.cjs');
7
7
  var react = require('react');
8
8
  var jsxRuntime = require('react/jsx-runtime');
9
9
  var legacy = require('react-grid-layout/legacy');
@@ -151,8 +151,8 @@ function DashboardProvider({
151
151
  lazyLoading = DEFAULT_LAZY_LOADING,
152
152
  children
153
153
  }) {
154
- const { client } = chunkNY6TZLST_cjs.useAnalytics();
155
- const crossFilterContext = chunkNY6TZLST_cjs.useCrossFilterOptional();
154
+ const { client } = chunkPG7QBH3G_cjs.useAnalytics();
155
+ const crossFilterContext = chunkPG7QBH3G_cjs.useCrossFilterOptional();
156
156
  const lazyLoadingEnabled = lazyLoading.enabled ?? true;
157
157
  const lazyLoadingEnabledRef = react.useRef(lazyLoadingEnabled);
158
158
  lazyLoadingEnabledRef.current = lazyLoadingEnabled;
@@ -171,6 +171,7 @@ function DashboardProvider({
171
171
  const clientRef = react.useRef(client);
172
172
  clientRef.current = client;
173
173
  const loadedDashboardRef = react.useRef(null);
174
+ const abortControllerRef = react.useRef(null);
174
175
  const setDashboardData = react.useCallback((data) => {
175
176
  setDashboard(data);
176
177
  const defaults = data.filters.filter((f) => f.default_value !== void 0).map((f) => ({
@@ -181,7 +182,8 @@ function DashboardProvider({
181
182
  if (!lazyLoadingEnabledRef.current) {
182
183
  const initialLoadingState = {};
183
184
  data.widgets.forEach((widget) => {
184
- if (widget.query) {
185
+ const isSqlMode = widget.config?.data_source_mode === "sql" && widget.config?.raw_sql;
186
+ if (widget.query || isSqlMode) {
185
187
  initialLoadingState[widget.id] = true;
186
188
  }
187
189
  });
@@ -189,8 +191,9 @@ function DashboardProvider({
189
191
  }
190
192
  }, []);
191
193
  const executeWidgetQuery = react.useCallback(
192
- async (widget, currentDashboard, currentFilters, currentCrossFilters, bypassCache = false) => {
193
- if (!widget.query) {
194
+ async (widget, currentDashboard, currentFilters, currentCrossFilters, bypassCache = false, signal) => {
195
+ const isSqlMode = widget.config?.data_source_mode === "sql" && widget.config?.raw_sql;
196
+ if (!widget.query && !isSqlMode) {
194
197
  return;
195
198
  }
196
199
  setWidgetLoading((prev) => ({ ...prev, [widget.id]: true }));
@@ -203,22 +206,32 @@ function DashboardProvider({
203
206
  return next;
204
207
  });
205
208
  try {
206
- let query = applyFiltersToQuery(
207
- widget.query,
208
- currentDashboard,
209
- currentFilters
210
- );
211
- query = applyCrossFiltersToQuery(query, currentCrossFilters, widget.id);
212
- const result = await client.executeQuery(query, bypassCache);
209
+ let result;
210
+ if (isSqlMode) {
211
+ result = await client.executeSQL(widget.config.raw_sql);
212
+ } else {
213
+ let query = applyFiltersToQuery(
214
+ widget.query,
215
+ currentDashboard,
216
+ currentFilters
217
+ );
218
+ query = applyCrossFiltersToQuery(query, currentCrossFilters, widget.id);
219
+ result = await client.executeQuery(query, bypassCache, signal);
220
+ }
221
+ if (signal?.aborted) return;
213
222
  setWidgetResults((prev) => ({ ...prev, [widget.id]: result }));
214
223
  const refreshTime = result.cached_at ?? Date.now() / 1e3;
215
224
  setWidgetRefreshTimes((prev) => ({ ...prev, [widget.id]: refreshTime }));
216
225
  } catch (err) {
226
+ if (err instanceof Error && err.name === "AbortError") {
227
+ return;
228
+ }
217
229
  setWidgetErrors((prev) => ({
218
230
  ...prev,
219
231
  [widget.id]: err instanceof Error ? err : new Error("Query failed")
220
232
  }));
221
233
  } finally {
234
+ if (signal?.aborted) return;
222
235
  setWidgetLoading((prev) => ({ ...prev, [widget.id]: false }));
223
236
  if (bypassCache) {
224
237
  setRefreshingWidgets((prev) => {
@@ -232,9 +245,12 @@ function DashboardProvider({
232
245
  [client]
233
246
  );
234
247
  const executeWidgetsInBatches = react.useCallback(
235
- async (widgets, currentDashboard, currentFilters, currentCrossFilters, bypassCache = false, currentBatchSize = batchSize) => {
236
- const widgetsWithQueries = widgets.filter((w) => w.query !== null);
248
+ async (widgets, currentDashboard, currentFilters, currentCrossFilters, bypassCache = false, currentBatchSize = batchSize, signal) => {
249
+ const widgetsWithQueries = widgets.filter(
250
+ (w) => w.query !== null || w.config?.data_source_mode === "sql" && w.config?.raw_sql
251
+ );
237
252
  for (let i = 0; i < widgetsWithQueries.length; i += currentBatchSize) {
253
+ if (signal?.aborted) return;
238
254
  const batch = widgetsWithQueries.slice(i, i + currentBatchSize);
239
255
  await Promise.all(
240
256
  batch.map(
@@ -243,7 +259,8 @@ function DashboardProvider({
243
259
  currentDashboard,
244
260
  currentFilters,
245
261
  currentCrossFilters,
246
- bypassCache
262
+ bypassCache,
263
+ signal
247
264
  )
248
265
  )
249
266
  );
@@ -255,16 +272,19 @@ function DashboardProvider({
255
272
  async (currentDashboard, currentFilters, currentCrossFilters) => {
256
273
  const requestId = Math.random().toString(36).substring(2, 11);
257
274
  requestIdRef.current = requestId;
275
+ const signal = abortControllerRef.current?.signal;
258
276
  await executeWidgetsInBatches(
259
277
  currentDashboard.widgets,
260
278
  currentDashboard,
261
279
  currentFilters,
262
280
  currentCrossFilters,
263
- false
281
+ false,
264
282
  // Don't bypass cache on initial load
283
+ batchSize,
284
+ signal
265
285
  );
266
286
  },
267
- [executeWidgetsInBatches]
287
+ [executeWidgetsInBatches, batchSize]
268
288
  );
269
289
  const refreshDashboard = react.useCallback(async () => {
270
290
  if (!dashboard) return;
@@ -427,16 +447,19 @@ function DashboardProvider({
427
447
  react.useEffect(() => {
428
448
  if (!lazyLoadingEnabled || !dashboard || isLoading) return;
429
449
  const widgetsToLoad = dashboard.widgets.filter(
430
- (w) => visibleWidgets.has(w.id) && w.query !== null && !widgetResults[w.id] && !widgetLoading[w.id]
450
+ (w) => visibleWidgets.has(w.id) && (w.query !== null || w.config?.data_source_mode === "sql" && w.config?.raw_sql) && !widgetResults[w.id] && !widgetLoading[w.id]
431
451
  );
432
452
  if (widgetsToLoad.length > 0) {
453
+ const signal = abortControllerRef.current?.signal;
433
454
  executeWidgetsInBatches(
434
455
  widgetsToLoad,
435
456
  dashboard,
436
457
  filterValues,
437
458
  crossFilters,
438
- false
459
+ false,
439
460
  // Don't bypass cache
461
+ batchSize,
462
+ signal
440
463
  );
441
464
  }
442
465
  }, [
@@ -448,7 +471,8 @@ function DashboardProvider({
448
471
  widgetLoading,
449
472
  filterValues,
450
473
  crossFilters,
451
- executeWidgetsInBatches
474
+ executeWidgetsInBatches,
475
+ batchSize
452
476
  ]);
453
477
  const filterValuesKey = JSON.stringify(filterValues);
454
478
  const prevFilterValuesRef = react.useRef(filterValuesKey);
@@ -457,16 +481,21 @@ function DashboardProvider({
457
481
  if (prevFilterValuesRef.current === filterValuesKey) return;
458
482
  prevFilterValuesRef.current = filterValuesKey;
459
483
  const widgetsToRefresh = dashboard.widgets.filter(
460
- (w) => everVisibleWidgets.has(w.id) && w.query !== null && widgetResults[w.id]
484
+ (w) => everVisibleWidgets.has(w.id) && (w.query !== null || w.config?.data_source_mode === "sql" && w.config?.raw_sql) && widgetResults[w.id]
461
485
  // Only re-execute if previously loaded
462
486
  );
463
487
  if (widgetsToRefresh.length > 0) {
488
+ abortControllerRef.current?.abort();
489
+ const controller = new AbortController();
490
+ abortControllerRef.current = controller;
464
491
  executeWidgetsInBatches(
465
492
  widgetsToRefresh,
466
493
  dashboard,
467
494
  filterValues,
468
495
  crossFilters,
469
- false
496
+ false,
497
+ batchSize,
498
+ controller.signal
470
499
  );
471
500
  }
472
501
  }, [
@@ -478,8 +507,16 @@ function DashboardProvider({
478
507
  widgetResults,
479
508
  filterValues,
480
509
  crossFilters,
481
- executeWidgetsInBatches
510
+ executeWidgetsInBatches,
511
+ batchSize
482
512
  ]);
513
+ react.useEffect(() => {
514
+ const controller = new AbortController();
515
+ abortControllerRef.current = controller;
516
+ return () => {
517
+ controller.abort();
518
+ };
519
+ }, [dashboardId]);
483
520
  const contextValue = react.useMemo(
484
521
  () => ({
485
522
  dashboard,
@@ -1026,7 +1063,7 @@ function EditableDashboardLayout({
1026
1063
  className = ""
1027
1064
  }) {
1028
1065
  const { theme } = chunkLMTG3LRC_cjs.useTheme();
1029
- const { queueUpdate, status, error } = chunkNY6TZLST_cjs.useDebouncedLayoutSave({
1066
+ const { queueUpdate, status, error } = chunkPG7QBH3G_cjs.useDebouncedLayoutSave({
1030
1067
  dashboardId,
1031
1068
  debounceMs,
1032
1069
  savedDurationMs,
@@ -1074,7 +1111,7 @@ function EditableDashboardLayout({
1074
1111
  style: containerStyles2,
1075
1112
  "data-testid": "dashboard-container",
1076
1113
  children: [
1077
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: statusBarStyles, children: /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.AutoSaveIndicator, { status, error }) }),
1114
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: statusBarStyles, children: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.AutoSaveIndicator, { status, error }) }),
1078
1115
  /* @__PURE__ */ jsxRuntime.jsx(
1079
1116
  DashboardLayout,
1080
1117
  {
@@ -1151,7 +1188,7 @@ function WidgetHeader({
1151
1188
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: headerStyle, className: "prismiq-widget-header", children: [
1152
1189
  /* @__PURE__ */ jsxRuntime.jsx("h3", { style: titleStyle, children: title }),
1153
1190
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: actionsStyle, children: [
1154
- lastRefreshed !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { style: timestampStyle, title: `Last refreshed: ${new Date(lastRefreshed * 1e3).toLocaleString()}`, children: chunk4AVL6GQK_cjs.formatRelativeTime(lastRefreshed) }),
1191
+ lastRefreshed !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { style: timestampStyle, title: `Last refreshed: ${new Date(lastRefreshed * 1e3).toLocaleString()}`, children: chunkKXB2IZI2_cjs.formatRelativeTime(lastRefreshed) }),
1155
1192
  onRefresh && /* @__PURE__ */ jsxRuntime.jsx(
1156
1193
  "button",
1157
1194
  {
@@ -1162,7 +1199,7 @@ function WidgetHeader({
1162
1199
  "aria-label": isRefreshing ? "Refreshing..." : "Refresh widget",
1163
1200
  title: isRefreshing ? "Refreshing..." : "Refresh widget",
1164
1201
  children: /* @__PURE__ */ jsxRuntime.jsx(
1165
- chunkNY6TZLST_cjs.Icon,
1202
+ chunkPG7QBH3G_cjs.Icon,
1166
1203
  {
1167
1204
  name: "sync",
1168
1205
  size: 16,
@@ -1181,7 +1218,7 @@ function WidgetHeader({
1181
1218
  style: actionButtonStyle,
1182
1219
  className: "prismiq-widget-action-button",
1183
1220
  "aria-label": hyperlink.title ?? "Open link",
1184
- children: /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "link", size: 16 })
1221
+ children: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "link", size: 16 })
1185
1222
  }
1186
1223
  )
1187
1224
  ] }),
@@ -1249,7 +1286,7 @@ function TextContent({ config }) {
1249
1286
  "div",
1250
1287
  {
1251
1288
  style: contentStyle,
1252
- dangerouslySetInnerHTML: { __html: chunk4AVL6GQK_cjs.parseMarkdownSafe(config.content, codeStyle) }
1289
+ dangerouslySetInnerHTML: { __html: chunkKXB2IZI2_cjs.parseMarkdownSafe(config.content, codeStyle) }
1253
1290
  }
1254
1291
  );
1255
1292
  }
@@ -1376,7 +1413,7 @@ function WidgetContent({
1376
1413
  isRefreshing = false
1377
1414
  }) {
1378
1415
  const { theme } = chunkLMTG3LRC_cjs.useTheme();
1379
- const crossFilterContext = chunkNY6TZLST_cjs.useCrossFilterOptional();
1416
+ const crossFilterContext = chunkPG7QBH3G_cjs.useCrossFilterOptional();
1380
1417
  const data = react.useMemo(() => result ? resultToDataPoints(result) : [], [result]);
1381
1418
  const chartTypesWithCrossFilter = ["bar_chart", "pie_chart", "line_chart", "area_chart"];
1382
1419
  const defaultCrossFilterEnabled = chartTypesWithCrossFilter.includes(widget.type);
@@ -1415,7 +1452,7 @@ function WidgetContent({
1415
1452
  );
1416
1453
  const dateFormatters = react.useMemo(() => {
1417
1454
  if (widget.type === "table" && widget.config.dateFormats) {
1418
- return chunk4AVL6GQK_cjs.createDateFormatters(widget.config.dateFormats);
1455
+ return chunkKXB2IZI2_cjs.createDateFormatters(widget.config.dateFormats);
1419
1456
  }
1420
1457
  return void 0;
1421
1458
  }, [widget.type, widget.config.dateFormats]);
@@ -1452,6 +1489,9 @@ function WidgetContent({
1452
1489
  if (widget.type === "text") {
1453
1490
  return /* @__PURE__ */ jsxRuntime.jsx("div", { style: containerStyle, children: /* @__PURE__ */ jsxRuntime.jsx(TextContent, { config: widget.config }) });
1454
1491
  }
1492
+ if (!result && !error && widget.query) {
1493
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { style: containerStyle, children: /* @__PURE__ */ jsxRuntime.jsx(LoadingState, {}) });
1494
+ }
1455
1495
  if (!result || result.row_count === 0) {
1456
1496
  return /* @__PURE__ */ jsxRuntime.jsx("div", { style: containerStyle, children: /* @__PURE__ */ jsxRuntime.jsx(EmptyState2, {}) });
1457
1497
  }
@@ -1467,7 +1507,7 @@ function WidgetContent({
1467
1507
  const comparisonValue = widget.config.trend_comparison ? result.rows[0]?.[result.columns.indexOf(widget.config.trend_comparison)] : void 0;
1468
1508
  return wrapWithContainer(
1469
1509
  /* @__PURE__ */ jsxRuntime.jsx(
1470
- chunkNK7HKX2J_cjs.MetricCard,
1510
+ chunk73TPDGXB_cjs.MetricCard,
1471
1511
  {
1472
1512
  title: "",
1473
1513
  value: typeof value === "number" ? value : Number(value) || 0,
@@ -1487,7 +1527,7 @@ function WidgetContent({
1487
1527
  case "bar_chart":
1488
1528
  return wrapWithContainer(
1489
1529
  /* @__PURE__ */ jsxRuntime.jsx(
1490
- chunkNK7HKX2J_cjs.BarChart,
1530
+ chunk73TPDGXB_cjs.BarChart,
1491
1531
  {
1492
1532
  data,
1493
1533
  xAxis,
@@ -1513,7 +1553,7 @@ function WidgetContent({
1513
1553
  case "line_chart":
1514
1554
  return wrapWithContainer(
1515
1555
  /* @__PURE__ */ jsxRuntime.jsx(
1516
- chunkNK7HKX2J_cjs.LineChart,
1556
+ chunk73TPDGXB_cjs.LineChart,
1517
1557
  {
1518
1558
  data,
1519
1559
  xAxis,
@@ -1535,7 +1575,7 @@ function WidgetContent({
1535
1575
  case "area_chart":
1536
1576
  return wrapWithContainer(
1537
1577
  /* @__PURE__ */ jsxRuntime.jsx(
1538
- chunkNK7HKX2J_cjs.AreaChart,
1578
+ chunk73TPDGXB_cjs.AreaChart,
1539
1579
  {
1540
1580
  data,
1541
1581
  xAxis,
@@ -1554,7 +1594,7 @@ function WidgetContent({
1554
1594
  case "pie_chart":
1555
1595
  return wrapWithContainer(
1556
1596
  /* @__PURE__ */ jsxRuntime.jsx(
1557
- chunkNK7HKX2J_cjs.PieChart,
1597
+ chunk73TPDGXB_cjs.PieChart,
1558
1598
  {
1559
1599
  data,
1560
1600
  labelColumn: xAxis,
@@ -1573,7 +1613,7 @@ function WidgetContent({
1573
1613
  case "scatter_chart":
1574
1614
  return wrapWithContainer(
1575
1615
  /* @__PURE__ */ jsxRuntime.jsx(
1576
- chunkNK7HKX2J_cjs.ScatterChart,
1616
+ chunk73TPDGXB_cjs.ScatterChart,
1577
1617
  {
1578
1618
  data,
1579
1619
  xAxis,
@@ -1588,10 +1628,22 @@ function WidgetContent({
1588
1628
  const dimensionColumns = result.columns.filter(
1589
1629
  (col) => col !== widget.config.pivot_column && col !== widget.config.value_column
1590
1630
  );
1591
- tableResult = chunk4AVL6GQK_cjs.pivotQueryResult(result, {
1631
+ let pivotColumnFormat;
1632
+ if (widget.config.dateFormats?.[widget.config.pivot_column]) {
1633
+ pivotColumnFormat = widget.config.dateFormats[widget.config.pivot_column];
1634
+ } else if (widget.query) {
1635
+ const pivotCol = widget.query.columns.find(
1636
+ (c) => c.alias === widget.config.pivot_column || c.column === widget.config.pivot_column
1637
+ );
1638
+ if (pivotCol?.date_format) {
1639
+ pivotColumnFormat = pivotCol.date_format;
1640
+ }
1641
+ }
1642
+ tableResult = chunkKXB2IZI2_cjs.pivotQueryResult(result, {
1592
1643
  pivotColumn: widget.config.pivot_column,
1593
1644
  valueColumn: widget.config.value_column,
1594
- dimensionColumns
1645
+ dimensionColumns,
1646
+ pivotColumnFormat
1595
1647
  });
1596
1648
  }
1597
1649
  const tableContainerStyle = {
@@ -1603,7 +1655,7 @@ function WidgetContent({
1603
1655
  position: "relative"
1604
1656
  };
1605
1657
  const tableContent = /* @__PURE__ */ jsxRuntime.jsx(
1606
- chunkNY6TZLST_cjs.ResultsTable,
1658
+ chunkPG7QBH3G_cjs.ResultsTable,
1607
1659
  {
1608
1660
  result: tableResult,
1609
1661
  pageSize: widget.config.page_size ?? 10,
@@ -1742,7 +1794,7 @@ function WidgetContainer({
1742
1794
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: contentStyles, children }),
1743
1795
  editable && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: overlayStyles, children: [
1744
1796
  onDuplicate && /* @__PURE__ */ jsxRuntime.jsx(
1745
- chunkNY6TZLST_cjs.Button,
1797
+ chunkPG7QBH3G_cjs.Button,
1746
1798
  {
1747
1799
  size: "sm",
1748
1800
  variant: "secondary",
@@ -1752,11 +1804,11 @@ function WidgetContainer({
1752
1804
  },
1753
1805
  title: "Duplicate",
1754
1806
  "data-testid": "duplicate-widget-button",
1755
- children: /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "copy", size: 14 })
1807
+ children: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "copy", size: 14 })
1756
1808
  }
1757
1809
  ),
1758
1810
  onEdit && /* @__PURE__ */ jsxRuntime.jsx(
1759
- chunkNY6TZLST_cjs.Button,
1811
+ chunkPG7QBH3G_cjs.Button,
1760
1812
  {
1761
1813
  size: "sm",
1762
1814
  variant: "secondary",
@@ -1766,11 +1818,11 @@ function WidgetContainer({
1766
1818
  },
1767
1819
  title: "Edit",
1768
1820
  "data-testid": "edit-widget-button",
1769
- children: /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "edit", size: 14 })
1821
+ children: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "edit", size: 14 })
1770
1822
  }
1771
1823
  ),
1772
1824
  onDelete && /* @__PURE__ */ jsxRuntime.jsx(
1773
- chunkNY6TZLST_cjs.Button,
1825
+ chunkPG7QBH3G_cjs.Button,
1774
1826
  {
1775
1827
  size: "sm",
1776
1828
  variant: "danger",
@@ -1780,7 +1832,7 @@ function WidgetContainer({
1780
1832
  },
1781
1833
  title: "Delete",
1782
1834
  "data-testid": "delete-widget-button",
1783
- children: /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "trash", size: 14 })
1835
+ children: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "trash", size: 14 })
1784
1836
  }
1785
1837
  )
1786
1838
  ] }),
@@ -1958,7 +2010,7 @@ function DateRangeFilter({
1958
2010
  ] });
1959
2011
  }
1960
2012
  function useDynamicFilterOptions(filter, limit = 100) {
1961
- const { client } = chunkNY6TZLST_cjs.useAnalytics();
2013
+ const { client } = chunkPG7QBH3G_cjs.useAnalytics();
1962
2014
  const [isLoading, setIsLoading] = react.useState(false);
1963
2015
  const [options, setOptions] = react.useState([]);
1964
2016
  const [error, setError] = react.useState(null);
@@ -2255,7 +2307,7 @@ function MultiSelectFilter({
2255
2307
  disabled: isLoading,
2256
2308
  children: [
2257
2309
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: displayText }),
2258
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: isOpen ? "chevron-up" : "chevron-down", size: 14 })
2310
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: isOpen ? "chevron-up" : "chevron-down", size: 14 })
2259
2311
  ]
2260
2312
  }
2261
2313
  ),
@@ -2304,7 +2356,7 @@ function MultiSelectFilter({
2304
2356
  backgroundColor: isAllSelected ? theme.colors.primary : theme.colors.background,
2305
2357
  borderColor: isAllSelected ? theme.colors.primary : theme.colors.border
2306
2358
  },
2307
- children: isAllSelected && /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "check", size: 12, style: { color: "#fff" } })
2359
+ children: isAllSelected && /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "check", size: 12, style: { color: "#fff" } })
2308
2360
  }
2309
2361
  ),
2310
2362
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "All" })
@@ -2330,7 +2382,7 @@ function MultiSelectFilter({
2330
2382
  backgroundColor: isSelected ? theme.colors.primary : theme.colors.background,
2331
2383
  borderColor: isSelected ? theme.colors.primary : theme.colors.border
2332
2384
  },
2333
- children: isSelected && /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "check", size: 12, style: { color: "#fff" } })
2385
+ children: isSelected && /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "check", size: 12, style: { color: "#fff" } })
2334
2386
  }
2335
2387
  ),
2336
2388
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: option.label })
@@ -2425,7 +2477,7 @@ function TextFilter({
2425
2477
  justifyContent: "center"
2426
2478
  };
2427
2479
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: containerStyle, children: [
2428
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "search", size: 14, style: iconStyle }),
2480
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "search", size: 14, style: iconStyle }),
2429
2481
  /* @__PURE__ */ jsxRuntime.jsx(
2430
2482
  "input",
2431
2483
  {
@@ -2444,7 +2496,7 @@ function TextFilter({
2444
2496
  onClick: handleClear,
2445
2497
  style: clearButtonStyle,
2446
2498
  "aria-label": "Clear filter",
2447
- children: /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "x", size: 14 })
2499
+ children: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "x", size: 14 })
2448
2500
  }
2449
2501
  )
2450
2502
  ] });
@@ -2498,7 +2550,7 @@ function FilterBar({
2498
2550
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: filter.label }),
2499
2551
  renderFilter(filter, values, onChange)
2500
2552
  ] }, filter.id)),
2501
- onReset && /* @__PURE__ */ jsxRuntime.jsx("div", { style: actionsStyle, children: /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Button, { variant: "ghost", size: "sm", onClick: handleReset, children: "Reset" }) })
2553
+ onReset && /* @__PURE__ */ jsxRuntime.jsx("div", { style: actionsStyle, children: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Button, { variant: "ghost", size: "sm", onClick: handleReset, children: "Reset" }) })
2502
2554
  ] });
2503
2555
  }
2504
2556
  function renderFilter(filter, values, onChange) {
@@ -2572,7 +2624,7 @@ function DashboardContent({
2572
2624
  refreshWidget
2573
2625
  } = useDashboard();
2574
2626
  const { filters, values, setValue, resetAll } = useDashboardFilters();
2575
- const crossFilterContext = chunkNY6TZLST_cjs.useCrossFilterOptional();
2627
+ const crossFilterContext = chunkPG7QBH3G_cjs.useCrossFilterOptional();
2576
2628
  const renderWidget = react.useCallback(
2577
2629
  (widget) => /* @__PURE__ */ jsxRuntime.jsx(
2578
2630
  LazyWidget,
@@ -2715,7 +2767,7 @@ function DashboardContent({
2715
2767
  ] }, filter.sourceWidgetId)),
2716
2768
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1 } }),
2717
2769
  /* @__PURE__ */ jsxRuntime.jsx(
2718
- chunkNY6TZLST_cjs.Button,
2770
+ chunkPG7QBH3G_cjs.Button,
2719
2771
  {
2720
2772
  variant: "ghost",
2721
2773
  size: "sm",
@@ -2744,7 +2796,7 @@ function Dashboard({
2744
2796
  lazyLoading,
2745
2797
  className = ""
2746
2798
  }) {
2747
- return /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.CrossFilterProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
2799
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.CrossFilterProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
2748
2800
  DashboardProvider,
2749
2801
  {
2750
2802
  dashboardId: id,
@@ -2852,37 +2904,37 @@ function EditorToolbar({
2852
2904
  ) : /* @__PURE__ */ jsxRuntime.jsx("h2", { style: titleStyle, children: dashboardName || "New Dashboard" }),
2853
2905
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: actionsStyle, children: [
2854
2906
  /* @__PURE__ */ jsxRuntime.jsxs(
2855
- chunkNY6TZLST_cjs.Button,
2907
+ chunkPG7QBH3G_cjs.Button,
2856
2908
  {
2857
2909
  variant: "secondary",
2858
2910
  size: "sm",
2859
2911
  onClick: onAddWidget,
2860
2912
  children: [
2861
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "plus", size: 16 }),
2913
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "plus", size: 16 }),
2862
2914
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { marginLeft: theme.spacing.xs }, children: "Add Widget" })
2863
2915
  ]
2864
2916
  }
2865
2917
  ),
2866
2918
  onEditFilters && /* @__PURE__ */ jsxRuntime.jsxs(
2867
- chunkNY6TZLST_cjs.Button,
2919
+ chunkPG7QBH3G_cjs.Button,
2868
2920
  {
2869
2921
  variant: "ghost",
2870
2922
  size: "sm",
2871
2923
  onClick: onEditFilters,
2872
2924
  children: [
2873
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "filter", size: 16 }),
2925
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "filter", size: 16 }),
2874
2926
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { marginLeft: theme.spacing.xs }, children: "Filters" })
2875
2927
  ]
2876
2928
  }
2877
2929
  ),
2878
2930
  onSettings && /* @__PURE__ */ jsxRuntime.jsxs(
2879
- chunkNY6TZLST_cjs.Button,
2931
+ chunkPG7QBH3G_cjs.Button,
2880
2932
  {
2881
2933
  variant: "ghost",
2882
2934
  size: "sm",
2883
2935
  onClick: onSettings,
2884
2936
  children: [
2885
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "settings", size: 16 }),
2937
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "settings", size: 16 }),
2886
2938
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { marginLeft: theme.spacing.xs }, children: "Settings" })
2887
2939
  ]
2888
2940
  }
@@ -2892,7 +2944,7 @@ function EditorToolbar({
2892
2944
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: rightSectionStyle, children: [
2893
2945
  hasChanges && /* @__PURE__ */ jsxRuntime.jsx("span", { style: unsavedStyle, children: "Unsaved changes" }),
2894
2946
  /* @__PURE__ */ jsxRuntime.jsx(
2895
- chunkNY6TZLST_cjs.Button,
2947
+ chunkPG7QBH3G_cjs.Button,
2896
2948
  {
2897
2949
  variant: "ghost",
2898
2950
  size: "sm",
@@ -2902,7 +2954,7 @@ function EditorToolbar({
2902
2954
  }
2903
2955
  ),
2904
2956
  /* @__PURE__ */ jsxRuntime.jsx(
2905
- chunkNY6TZLST_cjs.Button,
2957
+ chunkPG7QBH3G_cjs.Button,
2906
2958
  {
2907
2959
  variant: "primary",
2908
2960
  size: "sm",
@@ -2997,7 +3049,9 @@ function WidgetTypeSelector({
2997
3049
  borderRadius: theme.radius.sm,
2998
3050
  border: `2px solid ${isSelected ? theme.colors.primary : theme.colors.border}`,
2999
3051
  cursor: "pointer",
3000
- transition: "all 0.15s ease"
3052
+ transition: "all 0.15s ease",
3053
+ minWidth: 0
3054
+ // Allow grid item to shrink below content width
3001
3055
  });
3002
3056
  const iconStyle = (isSelected) => ({
3003
3057
  width: "28px",
@@ -3024,9 +3078,7 @@ function WidgetTypeSelector({
3024
3078
  const descStyle = {
3025
3079
  fontSize: theme.fontSizes.xs,
3026
3080
  color: theme.colors.textMuted,
3027
- whiteSpace: "nowrap",
3028
- overflow: "hidden",
3029
- textOverflow: "ellipsis"
3081
+ whiteSpace: "nowrap"
3030
3082
  };
3031
3083
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `prismiq-widget-type-selector ${className}`, style: containerStyle, children: [
3032
3084
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Widget Type" }),
@@ -3049,7 +3101,7 @@ function WidgetTypeSelector({
3049
3101
  }
3050
3102
  },
3051
3103
  children: [
3052
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: iconStyle(isSelected), children: /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: widgetType.icon, size: 16 }) }),
3104
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: iconStyle(isSelected), children: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: widgetType.icon, size: 16 }) }),
3053
3105
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: textContainerStyle, children: [
3054
3106
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: nameLabelStyle, children: widgetType.label }),
3055
3107
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: descStyle, children: widgetType.description })
@@ -3076,6 +3128,7 @@ function WidgetPreview({
3076
3128
  title,
3077
3129
  config,
3078
3130
  query,
3131
+ rawSql,
3079
3132
  result,
3080
3133
  isLoading = false,
3081
3134
  error,
@@ -3130,13 +3183,14 @@ function WidgetPreview({
3130
3183
  };
3131
3184
  const previewWidget = createPreviewWidget(type, title, config, query);
3132
3185
  const needsQuery = type !== "text";
3133
- const showEmptyState = needsQuery && !query && !isLoading;
3134
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `prismiq-widget-preview ${className}`, style: containerStyle, children: [
3186
+ const hasDataSource = !!query || !!rawSql;
3187
+ const showEmptyState = needsQuery && !hasDataSource && !isLoading;
3188
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `prismiq-widget-preview ${className}`, style: containerStyle, "data-testid": "widget-preview", children: [
3135
3189
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: headerStyle, children: [
3136
3190
  /* @__PURE__ */ jsxRuntime.jsx("h3", { style: titleStyle, children: title || "Widget Preview" }),
3137
3191
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: labelStyle, children: "Preview" })
3138
3192
  ] }),
3139
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: contentStyle, children: showEmptyState ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: emptyStateStyle, children: [
3193
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: contentStyle, children: showEmptyState ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: emptyStateStyle, "data-testid": "widget-preview-empty", children: [
3140
3194
  /* @__PURE__ */ jsxRuntime.jsx(
3141
3195
  "div",
3142
3196
  {
@@ -3193,19 +3247,26 @@ function MetricConfig({
3193
3247
  onChange
3194
3248
  }) {
3195
3249
  const { theme } = chunkLMTG3LRC_cjs.useTheme();
3250
+ const { getDisplayName } = chunkPG7QBH3G_cjs.useSchema();
3196
3251
  const initialTable = query?.tables[0]?.name ?? "";
3197
3252
  const initialAggregation = query?.columns[0]?.aggregation ?? "count";
3198
- const initialColumn = query?.columns[0]?.column ?? "*";
3253
+ const rawInitialColumn = query?.columns[0]?.column ?? "*";
3254
+ const needsColumnForInitial = AGGREGATIONS.find((a) => a.value === initialAggregation)?.needsColumn ?? false;
3255
+ const initialColumn = rawInitialColumn === "*" && needsColumnForInitial ? "" : rawInitialColumn;
3256
+ const initialFilters = (query?.filters ?? []).map((f) => ({
3257
+ ...f,
3258
+ table_id: "t1"
3259
+ }));
3199
3260
  const [selectedTable, setSelectedTable] = react.useState(initialTable);
3200
3261
  const [aggregation, setAggregation] = react.useState(initialAggregation);
3201
3262
  const [selectedColumn, setSelectedColumn] = react.useState(initialColumn);
3202
- const [filters, setFilters] = react.useState(query?.filters ?? []);
3263
+ const [filters, setFilters] = react.useState(initialFilters);
3203
3264
  const tableOptions = react.useMemo(() => {
3204
3265
  return schema.tables.map((t) => ({
3205
3266
  value: t.name,
3206
- label: t.name
3267
+ label: getDisplayName(t.name)
3207
3268
  }));
3208
- }, [schema.tables]);
3269
+ }, [schema.tables, getDisplayName]);
3209
3270
  const currentTable = react.useMemo(() => {
3210
3271
  return schema.tables.find((t) => t.name === selectedTable);
3211
3272
  }, [schema.tables, selectedTable]);
@@ -3220,8 +3281,12 @@ function MetricConfig({
3220
3281
  const needsColumn = react.useMemo(() => {
3221
3282
  return AGGREGATIONS.find((a) => a.value === aggregation)?.needsColumn ?? false;
3222
3283
  }, [aggregation]);
3284
+ const isValidAggregation = react.useMemo(() => {
3285
+ return AGGREGATIONS.some((a) => a.value === aggregation);
3286
+ }, [aggregation]);
3223
3287
  react.useEffect(() => {
3224
3288
  if (!selectedTable) return;
3289
+ if (!isValidAggregation) return;
3225
3290
  const tableId = "t1";
3226
3291
  const tables = [{ id: tableId, name: selectedTable }];
3227
3292
  const column = needsColumn ? selectedColumn : "*";
@@ -3239,7 +3304,7 @@ function MetricConfig({
3239
3304
  filters: filters.length > 0 ? filters : void 0
3240
3305
  };
3241
3306
  onChange(queryDef);
3242
- }, [selectedTable, aggregation, selectedColumn, needsColumn, filters, onChange]);
3307
+ }, [selectedTable, aggregation, selectedColumn, needsColumn, isValidAggregation, filters, onChange]);
3243
3308
  const handleTableChange = react.useCallback((value) => {
3244
3309
  setSelectedTable(value);
3245
3310
  setSelectedColumn("");
@@ -3268,7 +3333,7 @@ function MetricConfig({
3268
3333
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
3269
3334
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "From Table" }),
3270
3335
  /* @__PURE__ */ jsxRuntime.jsx(
3271
- chunkNY6TZLST_cjs.Select,
3336
+ chunkPG7QBH3G_cjs.Select,
3272
3337
  {
3273
3338
  value: selectedTable,
3274
3339
  onChange: handleTableChange,
@@ -3279,7 +3344,7 @@ function MetricConfig({
3279
3344
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
3280
3345
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Metric" }),
3281
3346
  /* @__PURE__ */ jsxRuntime.jsx(
3282
- chunkNY6TZLST_cjs.Select,
3347
+ chunkPG7QBH3G_cjs.Select,
3283
3348
  {
3284
3349
  value: aggregation,
3285
3350
  onChange: (value) => setAggregation(value),
@@ -3294,7 +3359,7 @@ function MetricConfig({
3294
3359
  needsColumn && selectedTable && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
3295
3360
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Column" }),
3296
3361
  columnOptions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
3297
- chunkNY6TZLST_cjs.Select,
3362
+ chunkPG7QBH3G_cjs.Select,
3298
3363
  {
3299
3364
  value: selectedColumn,
3300
3365
  onChange: setSelectedColumn,
@@ -3305,7 +3370,7 @@ function MetricConfig({
3305
3370
  selectedTable && currentTable && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
3306
3371
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Filters (optional)" }),
3307
3372
  /* @__PURE__ */ jsxRuntime.jsx(
3308
- chunkNY6TZLST_cjs.FilterBuilder,
3373
+ chunkPG7QBH3G_cjs.FilterBuilder,
3309
3374
  {
3310
3375
  tables: [{ id: "t1", name: selectedTable }],
3311
3376
  filters,
@@ -3364,17 +3429,23 @@ function ChartConfig({
3364
3429
  onChange
3365
3430
  }) {
3366
3431
  const { theme } = chunkLMTG3LRC_cjs.useTheme();
3432
+ const { getDisplayName } = chunkPG7QBH3G_cjs.useSchema();
3367
3433
  const initialTables = query?.tables ?? [];
3368
3434
  const groupByCol = query?.columns.find((c) => c.aggregation === "none");
3369
3435
  const initialGroupBy = groupByCol?.column ?? query?.group_by?.[0]?.column ?? "";
3370
3436
  const initialGroupByTableId = groupByCol?.table_id ?? query?.tables?.[0]?.id ?? "t1";
3371
3437
  const initialDateTrunc = groupByCol?.date_trunc ?? "";
3372
- const initialMeasures = query?.columns.filter((c) => c.aggregation !== "none").map((c) => ({
3373
- // Store as table-qualified ref so parseColumnRef can resolve it correctly
3374
- column: c.table_id ? `${c.table_id}.${c.column}` : c.column,
3375
- aggregation: c.aggregation,
3376
- table_id: c.table_id
3377
- })) ?? [];
3438
+ const initialMeasures = query?.columns.filter((c) => c.aggregation !== "none").map((c) => {
3439
+ const isStarWithNonCount = (c.column === "*" || c.column.endsWith(".*")) && c.aggregation !== "count";
3440
+ const column = isStarWithNonCount ? "" : c.table_id ? `${c.table_id}.${c.column}` : c.column;
3441
+ return {
3442
+ column,
3443
+ aggregation: c.aggregation,
3444
+ table_id: c.table_id,
3445
+ // Preserve original alias to maintain compatibility with widget config
3446
+ alias: c.alias
3447
+ };
3448
+ }) ?? [];
3378
3449
  const initialJoins = query?.joins ?? [];
3379
3450
  const [tables, setTables] = react.useState(initialTables);
3380
3451
  const [joins, setJoins] = react.useState(initialJoins);
@@ -3395,9 +3466,9 @@ function ChartConfig({
3395
3466
  const tableOptions = react.useMemo(() => {
3396
3467
  return schema.tables.map((t) => ({
3397
3468
  value: t.name,
3398
- label: t.name
3469
+ label: getDisplayName(t.name)
3399
3470
  }));
3400
- }, [schema.tables]);
3471
+ }, [schema.tables, getDisplayName]);
3401
3472
  const currentTable = react.useMemo(() => {
3402
3473
  return schema.tables.find((t) => t.name === selectedTable);
3403
3474
  }, [schema.tables, selectedTable]);
@@ -3467,7 +3538,7 @@ function ChartConfig({
3467
3538
  const parsedMeasures = [];
3468
3539
  const invalidColumns = [];
3469
3540
  validMeasures.forEach((m, i) => {
3470
- const measureAlias = validMeasures.length > 1 ? `value_${i + 1}` : "value";
3541
+ const measureAlias = m.alias ?? (validMeasures.length > 1 ? `value_${i + 1}` : "value");
3471
3542
  if (m.aggregation === "count" && (!m.column || m.column.endsWith(".*") || m.column === "*")) {
3472
3543
  parsedMeasures.push({
3473
3544
  table_id: m.table_id ?? tables[0]?.id ?? "t1",
@@ -3477,7 +3548,7 @@ function ChartConfig({
3477
3548
  });
3478
3549
  return;
3479
3550
  }
3480
- const parsed = chunk4AVL6GQK_cjs.parseColumnRef(m.column, tables[0]?.id ?? "t1");
3551
+ const parsed = chunkKXB2IZI2_cjs.parseColumnRef(m.column, tables[0]?.id ?? "t1");
3481
3552
  if (!parsed) {
3482
3553
  invalidColumns.push(m.column);
3483
3554
  return;
@@ -3531,6 +3602,9 @@ function ChartConfig({
3531
3602
  setJoins(
3532
3603
  (prev) => prev.filter((j) => tableIds.has(j.from_table_id) && tableIds.has(j.to_table_id))
3533
3604
  );
3605
+ setFilters(
3606
+ (prev) => prev.filter((f) => tableIds.has(f.table_id))
3607
+ );
3534
3608
  if (!tableIds.has(groupByTableId)) {
3535
3609
  setGroupByColumn("");
3536
3610
  setGroupByTableId(newTables[0]?.id ?? "t1");
@@ -3542,7 +3616,7 @@ function ChartConfig({
3542
3616
  setDateTrunc("");
3543
3617
  return;
3544
3618
  }
3545
- const parsed = chunk4AVL6GQK_cjs.parseColumnRef(value, groupByTableId);
3619
+ const parsed = chunkKXB2IZI2_cjs.parseColumnRef(value, groupByTableId);
3546
3620
  if (parsed) {
3547
3621
  setGroupByTableId(parsed.tableId);
3548
3622
  setGroupByColumn(parsed.column);
@@ -3601,7 +3675,7 @@ function ChartConfig({
3601
3675
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
3602
3676
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "From Table" }),
3603
3677
  /* @__PURE__ */ jsxRuntime.jsx(
3604
- chunkNY6TZLST_cjs.Select,
3678
+ chunkPG7QBH3G_cjs.Select,
3605
3679
  {
3606
3680
  value: selectedTable,
3607
3681
  onChange: handleTableChange,
@@ -3609,9 +3683,9 @@ function ChartConfig({
3609
3683
  }
3610
3684
  )
3611
3685
  ] }),
3612
- selectedTable && /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.CollapsibleSection, { title: "Join Tables", defaultOpen: tables.length > 1, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: theme.spacing.md }, children: [
3686
+ selectedTable && /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.CollapsibleSection, { title: "Join Tables", defaultOpen: tables.length > 1, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column", gap: theme.spacing.md }, children: [
3613
3687
  /* @__PURE__ */ jsxRuntime.jsx(
3614
- chunkNY6TZLST_cjs.TableSelector,
3688
+ chunkPG7QBH3G_cjs.TableSelector,
3615
3689
  {
3616
3690
  schema,
3617
3691
  tables,
@@ -3623,7 +3697,7 @@ function ChartConfig({
3623
3697
  tables.length >= 2 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
3624
3698
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Join Conditions" }),
3625
3699
  /* @__PURE__ */ jsxRuntime.jsx(
3626
- chunkNY6TZLST_cjs.JoinBuilder,
3700
+ chunkPG7QBH3G_cjs.JoinBuilder,
3627
3701
  {
3628
3702
  schema,
3629
3703
  tables,
@@ -3637,7 +3711,7 @@ function ChartConfig({
3637
3711
  selectedTable && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
3638
3712
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Group By (X-Axis)" }),
3639
3713
  groupByOptions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
3640
- chunkNY6TZLST_cjs.Select,
3714
+ chunkPG7QBH3G_cjs.Select,
3641
3715
  {
3642
3716
  value: groupByValue,
3643
3717
  onChange: handleGroupByChange,
@@ -3649,7 +3723,7 @@ function ChartConfig({
3649
3723
  selectedTable && groupByColumn && isGroupByDate && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
3650
3724
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Date Granularity" }),
3651
3725
  /* @__PURE__ */ jsxRuntime.jsx(
3652
- chunkNY6TZLST_cjs.Select,
3726
+ chunkPG7QBH3G_cjs.Select,
3653
3727
  {
3654
3728
  value: dateTrunc,
3655
3729
  onChange: (value) => setDateTrunc(value),
@@ -3658,8 +3732,8 @@ function ChartConfig({
3658
3732
  ),
3659
3733
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: helpTextStyle, children: "Truncate dates to this interval" })
3660
3734
  ] }),
3661
- selectedTable && isGroupByDate && /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.CollapsibleSection, { title: "Time Series Options", defaultOpen: timeSeries !== void 0, children: /* @__PURE__ */ jsxRuntime.jsx(
3662
- chunkNY6TZLST_cjs.TimeSeriesConfig,
3735
+ selectedTable && isGroupByDate && /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.CollapsibleSection, { title: "Time Series Options", defaultOpen: timeSeries !== void 0, children: /* @__PURE__ */ jsxRuntime.jsx(
3736
+ chunkPG7QBH3G_cjs.TimeSeriesConfig,
3663
3737
  {
3664
3738
  schema,
3665
3739
  tables,
@@ -3672,7 +3746,7 @@ function ChartConfig({
3672
3746
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Measures (Y-Axis)" }),
3673
3747
  measures.map((measure, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: measureRowStyle, children: [
3674
3748
  /* @__PURE__ */ jsxRuntime.jsx(
3675
- chunkNY6TZLST_cjs.Select,
3749
+ chunkPG7QBH3G_cjs.Select,
3676
3750
  {
3677
3751
  value: measure.aggregation,
3678
3752
  onChange: (value) => updateMeasure(index, { aggregation: value }),
@@ -3683,7 +3757,7 @@ function ChartConfig({
3683
3757
  measure.aggregation !== "count" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3684
3758
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: theme.colors.textMuted }, children: "of" }),
3685
3759
  measureColumnOptions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
3686
- chunkNY6TZLST_cjs.Select,
3760
+ chunkPG7QBH3G_cjs.Select,
3687
3761
  {
3688
3762
  value: measure.column,
3689
3763
  onChange: (value) => updateMeasure(index, { column: value }),
@@ -3692,17 +3766,17 @@ function ChartConfig({
3692
3766
  }
3693
3767
  ) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: { ...helpTextStyle, flex: 1 }, children: "No numeric columns" })
3694
3768
  ] }),
3695
- measures.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Button, { variant: "ghost", size: "sm", onClick: () => removeMeasure(index), children: /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "x", size: 14 }) })
3769
+ measures.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Button, { variant: "ghost", size: "sm", onClick: () => removeMeasure(index), children: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "x", size: 14 }) })
3696
3770
  ] }, measureIdsRef.current[index])),
3697
3771
  /* @__PURE__ */ jsxRuntime.jsxs(
3698
- chunkNY6TZLST_cjs.Button,
3772
+ chunkPG7QBH3G_cjs.Button,
3699
3773
  {
3700
3774
  variant: "ghost",
3701
3775
  size: "sm",
3702
3776
  onClick: addMeasure,
3703
3777
  style: { alignSelf: "flex-start" },
3704
3778
  children: [
3705
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "plus", size: 14 }),
3779
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "plus", size: 14 }),
3706
3780
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { marginLeft: theme.spacing.xs }, children: "Add measure" })
3707
3781
  ]
3708
3782
  }
@@ -3712,7 +3786,7 @@ function ChartConfig({
3712
3786
  selectedTable && currentTable && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
3713
3787
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Filters (optional)" }),
3714
3788
  /* @__PURE__ */ jsxRuntime.jsx(
3715
- chunkNY6TZLST_cjs.FilterBuilder,
3789
+ chunkPG7QBH3G_cjs.FilterBuilder,
3716
3790
  {
3717
3791
  tables,
3718
3792
  filters,
@@ -3722,12 +3796,12 @@ function ChartConfig({
3722
3796
  )
3723
3797
  ] }),
3724
3798
  selectedTable && /* @__PURE__ */ jsxRuntime.jsx(
3725
- chunkNY6TZLST_cjs.CollapsibleSection,
3799
+ chunkPG7QBH3G_cjs.CollapsibleSection,
3726
3800
  {
3727
3801
  title: "Calculated Fields",
3728
3802
  defaultOpen: calculatedFields.length > 0,
3729
3803
  children: /* @__PURE__ */ jsxRuntime.jsx(
3730
- chunkNY6TZLST_cjs.CalculatedFieldBuilder,
3804
+ chunkPG7QBH3G_cjs.CalculatedFieldBuilder,
3731
3805
  {
3732
3806
  fields: calculatedFields,
3733
3807
  onChange: setCalculatedFields,
@@ -3785,25 +3859,31 @@ function PieConfig({
3785
3859
  onChange
3786
3860
  }) {
3787
3861
  const { theme } = chunkLMTG3LRC_cjs.useTheme();
3862
+ const { getDisplayName } = chunkPG7QBH3G_cjs.useSchema();
3788
3863
  const initialTable = query?.tables[0]?.name ?? "";
3789
3864
  const labelCol = query?.columns.find((c) => c.aggregation === "none");
3790
3865
  const initialLabel = labelCol?.column ?? "";
3791
3866
  const initialDateTrunc = labelCol?.date_trunc ?? "";
3792
3867
  const measureCol = query?.columns.find((c) => c.aggregation !== "none");
3793
- const initialValueColumn = measureCol?.column ?? "";
3868
+ const rawInitialValueColumn = measureCol?.column ?? "";
3794
3869
  const initialAggregation = measureCol?.aggregation ?? "sum";
3870
+ const initialValueColumn = rawInitialValueColumn === "*" && initialAggregation !== "count" ? "" : rawInitialValueColumn;
3871
+ const initialFilters = (query?.filters ?? []).map((f) => ({
3872
+ ...f,
3873
+ table_id: "t1"
3874
+ }));
3795
3875
  const [selectedTable, setSelectedTable] = react.useState(initialTable);
3796
3876
  const [labelColumn, setLabelColumn] = react.useState(initialLabel);
3797
3877
  const [dateTrunc, setDateTrunc] = react.useState(initialDateTrunc);
3798
3878
  const [valueColumn, setValueColumn] = react.useState(initialValueColumn);
3799
3879
  const [aggregation, setAggregation] = react.useState(initialAggregation);
3800
- const [filters, setFilters] = react.useState(query?.filters ?? []);
3880
+ const [filters, setFilters] = react.useState(initialFilters);
3801
3881
  const tableOptions = react.useMemo(() => {
3802
3882
  return schema.tables.map((t) => ({
3803
3883
  value: t.name,
3804
- label: t.name
3884
+ label: getDisplayName(t.name)
3805
3885
  }));
3806
- }, [schema.tables]);
3886
+ }, [schema.tables, getDisplayName]);
3807
3887
  const currentTable = react.useMemo(() => {
3808
3888
  return schema.tables.find((t) => t.name === selectedTable);
3809
3889
  }, [schema.tables, selectedTable]);
@@ -3828,8 +3908,12 @@ function PieConfig({
3828
3908
  label: `${c.name} (${c.data_type})`
3829
3909
  }));
3830
3910
  }, [currentTable]);
3911
+ const isValidAggregation = react.useMemo(() => {
3912
+ return AGGREGATIONS3.some((a) => a.value === aggregation);
3913
+ }, [aggregation]);
3831
3914
  react.useEffect(() => {
3832
3915
  if (!selectedTable || !labelColumn) return;
3916
+ if (!isValidAggregation) return;
3833
3917
  const needsValueColumn = aggregation !== "count";
3834
3918
  if (needsValueColumn && !valueColumn) return;
3835
3919
  const tableId = "t1";
@@ -3859,7 +3943,7 @@ function PieConfig({
3859
3943
  order_by: [{ table_id: tableId, column: labelColumn, direction: "ASC" }]
3860
3944
  };
3861
3945
  onChange(queryDef);
3862
- }, [selectedTable, labelColumn, dateTrunc, valueColumn, aggregation, filters, onChange]);
3946
+ }, [selectedTable, labelColumn, dateTrunc, valueColumn, aggregation, isValidAggregation, filters, onChange]);
3863
3947
  const handleTableChange = react.useCallback((value) => {
3864
3948
  setSelectedTable(value);
3865
3949
  setLabelColumn("");
@@ -3901,7 +3985,7 @@ function PieConfig({
3901
3985
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
3902
3986
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "From Table" }),
3903
3987
  /* @__PURE__ */ jsxRuntime.jsx(
3904
- chunkNY6TZLST_cjs.Select,
3988
+ chunkPG7QBH3G_cjs.Select,
3905
3989
  {
3906
3990
  value: selectedTable,
3907
3991
  onChange: handleTableChange,
@@ -3912,7 +3996,7 @@ function PieConfig({
3912
3996
  selectedTable && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
3913
3997
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Slices (Labels)" }),
3914
3998
  labelOptions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
3915
- chunkNY6TZLST_cjs.Select,
3999
+ chunkPG7QBH3G_cjs.Select,
3916
4000
  {
3917
4001
  value: labelColumn,
3918
4002
  onChange: handleLabelChange,
@@ -3924,7 +4008,7 @@ function PieConfig({
3924
4008
  selectedTable && labelColumn && isLabelDate && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
3925
4009
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Date Granularity" }),
3926
4010
  /* @__PURE__ */ jsxRuntime.jsx(
3927
- chunkNY6TZLST_cjs.Select,
4011
+ chunkPG7QBH3G_cjs.Select,
3928
4012
  {
3929
4013
  value: dateTrunc,
3930
4014
  onChange: (value) => setDateTrunc(value),
@@ -3937,7 +4021,7 @@ function PieConfig({
3937
4021
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Size (Value)" }),
3938
4022
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: rowStyle, children: [
3939
4023
  /* @__PURE__ */ jsxRuntime.jsx(
3940
- chunkNY6TZLST_cjs.Select,
4024
+ chunkPG7QBH3G_cjs.Select,
3941
4025
  {
3942
4026
  value: aggregation,
3943
4027
  onChange: (value) => setAggregation(value),
@@ -3948,7 +4032,7 @@ function PieConfig({
3948
4032
  aggregation !== "count" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
3949
4033
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: theme.colors.textMuted }, children: "of" }),
3950
4034
  valueColumnOptions.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
3951
- chunkNY6TZLST_cjs.Select,
4035
+ chunkPG7QBH3G_cjs.Select,
3952
4036
  {
3953
4037
  value: valueColumn,
3954
4038
  onChange: setValueColumn,
@@ -3963,7 +4047,7 @@ function PieConfig({
3963
4047
  selectedTable && currentTable && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
3964
4048
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Filters (optional)" }),
3965
4049
  /* @__PURE__ */ jsxRuntime.jsx(
3966
- chunkNY6TZLST_cjs.FilterBuilder,
4050
+ chunkPG7QBH3G_cjs.FilterBuilder,
3967
4051
  {
3968
4052
  tables: [{ id: "t1", name: selectedTable }],
3969
4053
  filters,
@@ -3980,18 +4064,23 @@ function TableConfig({
3980
4064
  onChange
3981
4065
  }) {
3982
4066
  const { theme } = chunkLMTG3LRC_cjs.useTheme();
4067
+ const { getDisplayName } = chunkPG7QBH3G_cjs.useSchema();
3983
4068
  const initialTable = query?.tables[0]?.name ?? "";
3984
4069
  const initialColumns = query?.columns.map((c) => c.column) ?? [];
4070
+ const initialFilters = (query?.filters ?? []).map((f) => ({
4071
+ ...f,
4072
+ table_id: "t1"
4073
+ }));
3985
4074
  const [selectedTable, setSelectedTable] = react.useState(initialTable);
3986
4075
  const [selectedColumns, setSelectedColumns] = react.useState(initialColumns);
3987
- const [filters, setFilters] = react.useState(query?.filters ?? []);
4076
+ const [filters, setFilters] = react.useState(initialFilters);
3988
4077
  const [limit, setLimit] = react.useState(query?.limit ?? 100);
3989
4078
  const tableOptions = react.useMemo(() => {
3990
4079
  return schema.tables.map((t) => ({
3991
4080
  value: t.name,
3992
- label: t.name
4081
+ label: getDisplayName(t.name)
3993
4082
  }));
3994
- }, [schema.tables]);
4083
+ }, [schema.tables, getDisplayName]);
3995
4084
  const currentTable = react.useMemo(() => {
3996
4085
  return schema.tables.find((t) => t.name === selectedTable);
3997
4086
  }, [schema.tables, selectedTable]);
@@ -4081,7 +4170,7 @@ function TableConfig({
4081
4170
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
4082
4171
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "From Table" }),
4083
4172
  /* @__PURE__ */ jsxRuntime.jsx(
4084
- chunkNY6TZLST_cjs.Select,
4173
+ chunkPG7QBH3G_cjs.Select,
4085
4174
  {
4086
4175
  value: selectedTable,
4087
4176
  onChange: handleTableChange,
@@ -4098,7 +4187,7 @@ function TableConfig({
4098
4187
  ] })
4099
4188
  ] }),
4100
4189
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: columnsContainerStyle, children: currentTable.columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx(
4101
- chunkNY6TZLST_cjs.Checkbox,
4190
+ chunkPG7QBH3G_cjs.Checkbox,
4102
4191
  {
4103
4192
  label: `${col.name} (${col.data_type})`,
4104
4193
  checked: selectedColumns.includes(col.name),
@@ -4111,7 +4200,7 @@ function TableConfig({
4111
4200
  selectedTable && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
4112
4201
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Maximum Rows" }),
4113
4202
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: rowStyle, children: /* @__PURE__ */ jsxRuntime.jsx(
4114
- chunkNY6TZLST_cjs.Select,
4203
+ chunkPG7QBH3G_cjs.Select,
4115
4204
  {
4116
4205
  value: String(limit),
4117
4206
  onChange: (value) => setLimit(parseInt(value, 10)),
@@ -4130,7 +4219,7 @@ function TableConfig({
4130
4219
  selectedTable && currentTable && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
4131
4220
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Filters (optional)" }),
4132
4221
  /* @__PURE__ */ jsxRuntime.jsx(
4133
- chunkNY6TZLST_cjs.FilterBuilder,
4222
+ chunkPG7QBH3G_cjs.FilterBuilder,
4134
4223
  {
4135
4224
  tables: [{ id: "t1", name: selectedTable }],
4136
4225
  filters,
@@ -4214,11 +4303,11 @@ function HyperlinkSection({
4214
4303
  target
4215
4304
  });
4216
4305
  };
4217
- return /* @__PURE__ */ jsxRuntime.jsxs(chunkNY6TZLST_cjs.CollapsibleSection, { title: "Hyperlink", defaultOpen, children: [
4306
+ return /* @__PURE__ */ jsxRuntime.jsxs(chunkPG7QBH3G_cjs.CollapsibleSection, { title: "Hyperlink", defaultOpen, children: [
4218
4307
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
4219
4308
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "URL" }),
4220
4309
  /* @__PURE__ */ jsxRuntime.jsx(
4221
- chunkNY6TZLST_cjs.Input,
4310
+ chunkPG7QBH3G_cjs.Input,
4222
4311
  {
4223
4312
  value: hyperlink?.url || "",
4224
4313
  onChange: (e) => handleUrlChange(e.target.value),
@@ -4231,7 +4320,7 @@ function HyperlinkSection({
4231
4320
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
4232
4321
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Tooltip Text" }),
4233
4322
  /* @__PURE__ */ jsxRuntime.jsx(
4234
- chunkNY6TZLST_cjs.Input,
4323
+ chunkPG7QBH3G_cjs.Input,
4235
4324
  {
4236
4325
  value: hyperlink?.title || "",
4237
4326
  onChange: (e) => handleTitleChange(e.target.value),
@@ -4242,7 +4331,7 @@ function HyperlinkSection({
4242
4331
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
4243
4332
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Open In" }),
4244
4333
  /* @__PURE__ */ jsxRuntime.jsx(
4245
- chunkNY6TZLST_cjs.Select,
4334
+ chunkPG7QBH3G_cjs.Select,
4246
4335
  {
4247
4336
  value: hyperlink?.target || "_blank",
4248
4337
  onChange: handleTargetChange,
@@ -4318,14 +4407,14 @@ function ReferenceLinesSection({
4318
4407
  onChange(lines.filter((_, i) => i !== index));
4319
4408
  };
4320
4409
  return /* @__PURE__ */ jsxRuntime.jsxs(
4321
- chunkNY6TZLST_cjs.CollapsibleSection,
4410
+ chunkPG7QBH3G_cjs.CollapsibleSection,
4322
4411
  {
4323
4412
  title: "Reference Lines",
4324
4413
  defaultOpen: defaultOpen || lines.length > 0,
4325
4414
  children: [
4326
4415
  lines.map((line, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: lineRowStyle, children: [
4327
4416
  /* @__PURE__ */ jsxRuntime.jsx(
4328
- chunkNY6TZLST_cjs.Input,
4417
+ chunkPG7QBH3G_cjs.Input,
4329
4418
  {
4330
4419
  type: "number",
4331
4420
  value: String(line.value),
@@ -4335,7 +4424,7 @@ function ReferenceLinesSection({
4335
4424
  }
4336
4425
  ),
4337
4426
  /* @__PURE__ */ jsxRuntime.jsx(
4338
- chunkNY6TZLST_cjs.Input,
4427
+ chunkPG7QBH3G_cjs.Input,
4339
4428
  {
4340
4429
  value: line.label ?? "",
4341
4430
  onChange: (e) => updateLine(index, { label: e.target.value || void 0 }),
@@ -4354,7 +4443,7 @@ function ReferenceLinesSection({
4354
4443
  }
4355
4444
  ),
4356
4445
  /* @__PURE__ */ jsxRuntime.jsx(
4357
- chunkNY6TZLST_cjs.Select,
4446
+ chunkPG7QBH3G_cjs.Select,
4358
4447
  {
4359
4448
  value: line.lineStyle ?? "dashed",
4360
4449
  onChange: (value) => updateLine(index, {
@@ -4364,10 +4453,10 @@ function ReferenceLinesSection({
4364
4453
  style: { width: "90px" }
4365
4454
  }
4366
4455
  ),
4367
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Button, { variant: "ghost", size: "sm", onClick: () => removeLine(index), children: /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "x", size: 14 }) })
4456
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Button, { variant: "ghost", size: "sm", onClick: () => removeLine(index), children: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "x", size: 14 }) })
4368
4457
  ] }, lineIdsRef.current[index])),
4369
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: addButtonStyle, children: /* @__PURE__ */ jsxRuntime.jsxs(chunkNY6TZLST_cjs.Button, { variant: "ghost", size: "sm", onClick: addLine, children: [
4370
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "plus", size: 14 }),
4458
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: addButtonStyle, children: /* @__PURE__ */ jsxRuntime.jsxs(chunkPG7QBH3G_cjs.Button, { variant: "ghost", size: "sm", onClick: addLine, children: [
4459
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "plus", size: 14 }),
4371
4460
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { marginLeft: theme.spacing.xs }, children: "Add reference line" })
4372
4461
  ] }) })
4373
4462
  ]
@@ -4451,7 +4540,7 @@ function TextFormattingSection({
4451
4540
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: headerStyle, children: [
4452
4541
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Content" }),
4453
4542
  config.markdown && /* @__PURE__ */ jsxRuntime.jsx(
4454
- chunkNY6TZLST_cjs.Checkbox,
4543
+ chunkPG7QBH3G_cjs.Checkbox,
4455
4544
  {
4456
4545
  label: "Preview",
4457
4546
  checked: showPreview,
@@ -4465,7 +4554,7 @@ function TextFormattingSection({
4465
4554
  "div",
4466
4555
  {
4467
4556
  dangerouslySetInnerHTML: {
4468
- __html: chunk4AVL6GQK_cjs.parseMarkdownSafe(config.content ?? "")
4557
+ __html: chunkKXB2IZI2_cjs.parseMarkdownSafe(config.content ?? "")
4469
4558
  }
4470
4559
  }
4471
4560
  )
@@ -4481,7 +4570,7 @@ function TextFormattingSection({
4481
4570
  )
4482
4571
  ] }),
4483
4572
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: fieldStyle, children: /* @__PURE__ */ jsxRuntime.jsx(
4484
- chunkNY6TZLST_cjs.Checkbox,
4573
+ chunkPG7QBH3G_cjs.Checkbox,
4485
4574
  {
4486
4575
  label: "Enable Markdown",
4487
4576
  checked: config.markdown ?? false,
@@ -4492,7 +4581,7 @@ function TextFormattingSection({
4492
4581
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: halfFieldStyle, children: [
4493
4582
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Alignment" }),
4494
4583
  /* @__PURE__ */ jsxRuntime.jsx(
4495
- chunkNY6TZLST_cjs.Select,
4584
+ chunkPG7QBH3G_cjs.Select,
4496
4585
  {
4497
4586
  value: config.alignment ?? "Left",
4498
4587
  onChange: (value) => onChange("alignment", value),
@@ -4503,7 +4592,7 @@ function TextFormattingSection({
4503
4592
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: halfFieldStyle, children: [
4504
4593
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Font Size" }),
4505
4594
  /* @__PURE__ */ jsxRuntime.jsx(
4506
- chunkNY6TZLST_cjs.Select,
4595
+ chunkPG7QBH3G_cjs.Select,
4507
4596
  {
4508
4597
  value: config.fontSize ?? "Normal",
4509
4598
  onChange: (value) => onChange("fontSize", value),
@@ -4620,13 +4709,13 @@ function PivotConfigSection({
4620
4709
  ).map((col) => col.column);
4621
4710
  }, [query, config.pivot_column, config.value_column]);
4622
4711
  return /* @__PURE__ */ jsxRuntime.jsxs(
4623
- chunkNY6TZLST_cjs.CollapsibleSection,
4712
+ chunkPG7QBH3G_cjs.CollapsibleSection,
4624
4713
  {
4625
4714
  title: "Pivot Table",
4626
4715
  defaultOpen: defaultOpen || isPivotEnabled,
4627
4716
  children: [
4628
4717
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: fieldStyle, children: /* @__PURE__ */ jsxRuntime.jsx(
4629
- chunkNY6TZLST_cjs.Checkbox,
4718
+ chunkPG7QBH3G_cjs.Checkbox,
4630
4719
  {
4631
4720
  label: "Enable Pivot Mode",
4632
4721
  checked: isPivotEnabled,
@@ -4637,7 +4726,7 @@ function PivotConfigSection({
4637
4726
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
4638
4727
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Pivot Column" }),
4639
4728
  /* @__PURE__ */ jsxRuntime.jsx(
4640
- chunkNY6TZLST_cjs.Select,
4729
+ chunkPG7QBH3G_cjs.Select,
4641
4730
  {
4642
4731
  value: config.pivot_column ?? "",
4643
4732
  onChange: (value) => onChange("pivot_column", value || void 0),
@@ -4652,7 +4741,7 @@ function PivotConfigSection({
4652
4741
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
4653
4742
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Value Column" }),
4654
4743
  /* @__PURE__ */ jsxRuntime.jsx(
4655
- chunkNY6TZLST_cjs.Select,
4744
+ chunkPG7QBH3G_cjs.Select,
4656
4745
  {
4657
4746
  value: config.value_column ?? "",
4658
4747
  onChange: (value) => onChange("value_column", value || void 0),
@@ -4715,7 +4804,7 @@ function LayoutConstraintsSection({
4715
4804
  };
4716
4805
  const hasConstraints = position.minW !== void 0 || position.maxW !== void 0 || position.minH !== void 0 || position.maxH !== void 0;
4717
4806
  return /* @__PURE__ */ jsxRuntime.jsx(
4718
- chunkNY6TZLST_cjs.CollapsibleSection,
4807
+ chunkPG7QBH3G_cjs.CollapsibleSection,
4719
4808
  {
4720
4809
  title: "Size Constraints",
4721
4810
  defaultOpen: defaultOpen || hasConstraints,
@@ -4723,7 +4812,7 @@ function LayoutConstraintsSection({
4723
4812
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
4724
4813
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Min Width" }),
4725
4814
  /* @__PURE__ */ jsxRuntime.jsx(
4726
- chunkNY6TZLST_cjs.Input,
4815
+ chunkPG7QBH3G_cjs.Input,
4727
4816
  {
4728
4817
  type: "number",
4729
4818
  value: position.minW !== void 0 ? String(position.minW) : "",
@@ -4737,7 +4826,7 @@ function LayoutConstraintsSection({
4737
4826
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
4738
4827
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Max Width" }),
4739
4828
  /* @__PURE__ */ jsxRuntime.jsx(
4740
- chunkNY6TZLST_cjs.Input,
4829
+ chunkPG7QBH3G_cjs.Input,
4741
4830
  {
4742
4831
  type: "number",
4743
4832
  value: position.maxW !== void 0 ? String(position.maxW) : "",
@@ -4751,7 +4840,7 @@ function LayoutConstraintsSection({
4751
4840
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
4752
4841
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Min Height" }),
4753
4842
  /* @__PURE__ */ jsxRuntime.jsx(
4754
- chunkNY6TZLST_cjs.Input,
4843
+ chunkPG7QBH3G_cjs.Input,
4755
4844
  {
4756
4845
  type: "number",
4757
4846
  value: position.minH !== void 0 ? String(position.minH) : "",
@@ -4764,7 +4853,7 @@ function LayoutConstraintsSection({
4764
4853
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
4765
4854
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Max Height" }),
4766
4855
  /* @__PURE__ */ jsxRuntime.jsx(
4767
- chunkNY6TZLST_cjs.Input,
4856
+ chunkPG7QBH3G_cjs.Input,
4768
4857
  {
4769
4858
  type: "number",
4770
4859
  value: position.maxH !== void 0 ? String(position.maxH) : "",
@@ -4832,14 +4921,14 @@ function CrossFilterSection({
4832
4921
  });
4833
4922
  };
4834
4923
  return /* @__PURE__ */ jsxRuntime.jsxs(
4835
- chunkNY6TZLST_cjs.CollapsibleSection,
4924
+ chunkPG7QBH3G_cjs.CollapsibleSection,
4836
4925
  {
4837
4926
  title: "Cross-Filtering",
4838
4927
  defaultOpen: defaultOpen || crossFilterEnabled,
4839
4928
  children: [
4840
4929
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
4841
4930
  /* @__PURE__ */ jsxRuntime.jsx(
4842
- chunkNY6TZLST_cjs.Checkbox,
4931
+ chunkPG7QBH3G_cjs.Checkbox,
4843
4932
  {
4844
4933
  label: "Enable as filter source",
4845
4934
  checked: crossFilterEnabled,
@@ -4851,7 +4940,7 @@ function CrossFilterSection({
4851
4940
  crossFilterEnabled && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
4852
4941
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Filter Column" }),
4853
4942
  /* @__PURE__ */ jsxRuntime.jsx(
4854
- chunkNY6TZLST_cjs.Select,
4943
+ chunkPG7QBH3G_cjs.Select,
4855
4944
  {
4856
4945
  value: config.cross_filter?.column ?? config.x_axis ?? "",
4857
4946
  onChange: handleColumnChange,
@@ -4950,11 +5039,11 @@ function ValueFormattingSection({
4950
5039
  marginBottom: theme.spacing.xs
4951
5040
  };
4952
5041
  const isCurrency = config.valueFormat === "currency" || config.format === "currency";
4953
- return /* @__PURE__ */ jsxRuntime.jsxs(chunkNY6TZLST_cjs.CollapsibleSection, { title: "Value Formatting", defaultOpen, children: [
5042
+ return /* @__PURE__ */ jsxRuntime.jsxs(chunkPG7QBH3G_cjs.CollapsibleSection, { title: "Value Formatting", defaultOpen, children: [
4954
5043
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
4955
5044
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Format" }),
4956
5045
  /* @__PURE__ */ jsxRuntime.jsx(
4957
- chunkNY6TZLST_cjs.Select,
5046
+ chunkPG7QBH3G_cjs.Select,
4958
5047
  {
4959
5048
  value: config.valueFormat || config.format || "number",
4960
5049
  onChange: (value) => {
@@ -4969,7 +5058,7 @@ function ValueFormattingSection({
4969
5058
  isCurrency && showCurrency && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
4970
5059
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Currency Symbol" }),
4971
5060
  /* @__PURE__ */ jsxRuntime.jsx(
4972
- chunkNY6TZLST_cjs.Input,
5061
+ chunkPG7QBH3G_cjs.Input,
4973
5062
  {
4974
5063
  value: config.currencySymbol ?? "$",
4975
5064
  onChange: (e) => onChange("currencySymbol", e.target.value),
@@ -4981,7 +5070,7 @@ function ValueFormattingSection({
4981
5070
  showCompact && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
4982
5071
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Compact Notation" }),
4983
5072
  /* @__PURE__ */ jsxRuntime.jsx(
4984
- chunkNY6TZLST_cjs.Select,
5073
+ chunkPG7QBH3G_cjs.Select,
4985
5074
  {
4986
5075
  value: config.compactNotation || "",
4987
5076
  onChange: (value) => onChange("compactNotation", value ? value : null),
@@ -4992,7 +5081,7 @@ function ValueFormattingSection({
4992
5081
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
4993
5082
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Decimal Places" }),
4994
5083
  /* @__PURE__ */ jsxRuntime.jsx(
4995
- chunkNY6TZLST_cjs.Select,
5084
+ chunkPG7QBH3G_cjs.Select,
4996
5085
  {
4997
5086
  value: String(config.decimalDigits ?? 2),
4998
5087
  onChange: (value) => onChange("decimalDigits", parseInt(value, 10)),
@@ -5033,9 +5122,9 @@ function DisplayConfigSection({
5033
5122
  "pie_chart",
5034
5123
  "scatter_chart"
5035
5124
  ].includes(widgetType);
5036
- return /* @__PURE__ */ jsxRuntime.jsxs(chunkNY6TZLST_cjs.CollapsibleSection, { title: "Display Options", defaultOpen, children: [
5125
+ return /* @__PURE__ */ jsxRuntime.jsxs(chunkPG7QBH3G_cjs.CollapsibleSection, { title: "Display Options", defaultOpen, children: [
5037
5126
  showColorPalette && /* @__PURE__ */ jsxRuntime.jsx("div", { style: fieldStyle, children: /* @__PURE__ */ jsxRuntime.jsx(
5038
- chunkNY6TZLST_cjs.ColorPaletteSelector,
5127
+ chunkPG7QBH3G_cjs.ColorPaletteSelector,
5039
5128
  {
5040
5129
  value: config.colors,
5041
5130
  onChange: (colors) => onChange("colors", colors)
@@ -5044,7 +5133,7 @@ function DisplayConfigSection({
5044
5133
  showOrientation && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
5045
5134
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Orientation" }),
5046
5135
  /* @__PURE__ */ jsxRuntime.jsx(
5047
- chunkNY6TZLST_cjs.Select,
5136
+ chunkPG7QBH3G_cjs.Select,
5048
5137
  {
5049
5138
  value: config.orientation || "vertical",
5050
5139
  onChange: (value) => onChange("orientation", value),
@@ -5057,7 +5146,7 @@ function DisplayConfigSection({
5057
5146
  ] }),
5058
5147
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: rowStyle, children: [
5059
5148
  /* @__PURE__ */ jsxRuntime.jsx(
5060
- chunkNY6TZLST_cjs.Checkbox,
5149
+ chunkPG7QBH3G_cjs.Checkbox,
5061
5150
  {
5062
5151
  label: "Show Legend",
5063
5152
  checked: config.show_legend ?? true,
@@ -5065,7 +5154,7 @@ function DisplayConfigSection({
5065
5154
  }
5066
5155
  ),
5067
5156
  /* @__PURE__ */ jsxRuntime.jsx(
5068
- chunkNY6TZLST_cjs.Checkbox,
5157
+ chunkPG7QBH3G_cjs.Checkbox,
5069
5158
  {
5070
5159
  label: "Data Labels",
5071
5160
  checked: config.show_data_labels ?? false,
@@ -5073,7 +5162,7 @@ function DisplayConfigSection({
5073
5162
  }
5074
5163
  ),
5075
5164
  showStacked && /* @__PURE__ */ jsxRuntime.jsx(
5076
- chunkNY6TZLST_cjs.Checkbox,
5165
+ chunkPG7QBH3G_cjs.Checkbox,
5077
5166
  {
5078
5167
  label: "Stacked",
5079
5168
  checked: config.stacked ?? false,
@@ -5158,10 +5247,10 @@ function DateFormattingSection({
5158
5247
  fontSize: theme.fontSizes.sm,
5159
5248
  color: theme.colors.textMuted
5160
5249
  };
5161
- return /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.CollapsibleSection, { title: "Date Formatting", defaultOpen, children: dateColumns.map((col) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
5250
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.CollapsibleSection, { title: "Date Formatting", defaultOpen, children: dateColumns.map((col) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
5162
5251
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: columnNameStyle, children: col.alias }) }),
5163
5252
  /* @__PURE__ */ jsxRuntime.jsx(
5164
- chunkNY6TZLST_cjs.Select,
5253
+ chunkPG7QBH3G_cjs.Select,
5165
5254
  {
5166
5255
  value: config.dateFormats?.[col.name] || "",
5167
5256
  onChange: (value) => handleFormatChange(col.name, value),
@@ -5219,10 +5308,10 @@ function TrendConfigSection({
5219
5308
  color: theme.colors.textMuted,
5220
5309
  marginTop: theme.spacing.xs
5221
5310
  };
5222
- return /* @__PURE__ */ jsxRuntime.jsxs(chunkNY6TZLST_cjs.CollapsibleSection, { title: "Trend Comparison", defaultOpen, children: [
5311
+ return /* @__PURE__ */ jsxRuntime.jsxs(chunkPG7QBH3G_cjs.CollapsibleSection, { title: "Trend Comparison", defaultOpen, children: [
5223
5312
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
5224
5313
  /* @__PURE__ */ jsxRuntime.jsx(
5225
- chunkNY6TZLST_cjs.Checkbox,
5314
+ chunkPG7QBH3G_cjs.Checkbox,
5226
5315
  {
5227
5316
  label: "Show Trend Indicator",
5228
5317
  checked: config.showTrend ?? false,
@@ -5235,7 +5324,7 @@ function TrendConfigSection({
5235
5324
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
5236
5325
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Comparison Period" }),
5237
5326
  /* @__PURE__ */ jsxRuntime.jsx(
5238
- chunkNY6TZLST_cjs.Select,
5327
+ chunkPG7QBH3G_cjs.Select,
5239
5328
  {
5240
5329
  value: config.trendPeriod || "previous_period",
5241
5330
  onChange: (value) => onChange("trendPeriod", value),
@@ -5246,7 +5335,7 @@ function TrendConfigSection({
5246
5335
  dateColumnOptions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
5247
5336
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Date Column" }),
5248
5337
  /* @__PURE__ */ jsxRuntime.jsx(
5249
- chunkNY6TZLST_cjs.Select,
5338
+ chunkPG7QBH3G_cjs.Select,
5250
5339
  {
5251
5340
  value: config.trendDateColumn || "",
5252
5341
  onChange: (value) => onChange("trendDateColumn", value || void 0),
@@ -5292,7 +5381,8 @@ function WidgetEditorPage({
5292
5381
  onCancel
5293
5382
  }) {
5294
5383
  const { theme } = chunkLMTG3LRC_cjs.useTheme();
5295
- const { client } = chunkNY6TZLST_cjs.useAnalytics();
5384
+ const { client } = chunkPG7QBH3G_cjs.useAnalytics();
5385
+ const { enabled: llmEnabled, isLoading: llmStatusLoading } = chunkPG7QBH3G_cjs.useLLMStatus();
5296
5386
  const isNew = widget === null;
5297
5387
  const [type, setType] = react.useState(widget?.type ?? "bar_chart");
5298
5388
  const [title, setTitle] = react.useState(widget?.title ?? "New Widget");
@@ -5304,8 +5394,10 @@ function WidgetEditorPage({
5304
5394
  const [position, setPosition] = react.useState(
5305
5395
  widget?.position ?? { x: 0, y: 0, w: 6, h: 4, minW: 2, minH: 2 }
5306
5396
  );
5397
+ const [rawSql, setRawSql] = react.useState(widget?.config?.raw_sql ?? "");
5398
+ const [schemaOpen, setSchemaOpen] = react.useState(true);
5307
5399
  const [dataSourceMode, setDataSourceMode] = react.useState(
5308
- isNew ? "guided" : widget?.dataSourceMode ?? "guided"
5400
+ isNew ? "guided" : widget?.config?.data_source_mode ?? "guided"
5309
5401
  );
5310
5402
  const [previewResult, setPreviewResult] = react.useState(null);
5311
5403
  const [previewLoading, setPreviewLoading] = react.useState(false);
@@ -5328,6 +5420,24 @@ function WidgetEditorPage({
5328
5420
  []
5329
5421
  );
5330
5422
  const refreshPreview = react.useCallback(async () => {
5423
+ if (dataSourceMode === "sql") {
5424
+ if (!rawSql.trim() || !client) {
5425
+ setPreviewResult(null);
5426
+ return;
5427
+ }
5428
+ setPreviewLoading(true);
5429
+ setPreviewError(null);
5430
+ try {
5431
+ const result = await client.executeSQL(rawSql);
5432
+ setPreviewResult(result);
5433
+ } catch (err) {
5434
+ setPreviewError(err instanceof Error ? err : new Error("SQL execution failed"));
5435
+ setPreviewResult(null);
5436
+ } finally {
5437
+ setPreviewLoading(false);
5438
+ }
5439
+ return;
5440
+ }
5331
5441
  if (!query || !client) {
5332
5442
  setPreviewResult(null);
5333
5443
  return;
@@ -5343,15 +5453,38 @@ function WidgetEditorPage({
5343
5453
  } finally {
5344
5454
  setPreviewLoading(false);
5345
5455
  }
5346
- }, [query, client]);
5456
+ }, [query, rawSql, dataSourceMode, client]);
5347
5457
  react.useEffect(() => {
5458
+ if (dataSourceMode === "sql") {
5459
+ return;
5460
+ }
5348
5461
  if (query) {
5349
5462
  void refreshPreview();
5350
5463
  } else {
5351
5464
  setPreviewResult(null);
5352
5465
  setPreviewError(null);
5353
5466
  }
5354
- }, [query, refreshPreview]);
5467
+ }, [query, dataSourceMode, refreshPreview]);
5468
+ const queryHasAdvancedFeatures = react.useCallback((q) => {
5469
+ if (!q) return false;
5470
+ if (q.tables && q.tables.length > 1 && q.joins && q.joins.length > 0) return true;
5471
+ if (q.calculated_fields && q.calculated_fields.length > 0) return true;
5472
+ if (q.group_by && q.group_by.length > 0) return true;
5473
+ if (q.order_by && q.order_by.length > 0) return true;
5474
+ if (q.limit != null) return true;
5475
+ if (q.offset != null) return true;
5476
+ if (q.time_series) return true;
5477
+ return false;
5478
+ }, []);
5479
+ const handleModeSwitch = react.useCallback((newMode) => {
5480
+ if (newMode === "guided" && (dataSourceMode === "advanced" || dataSourceMode === "saved") && queryHasAdvancedFeatures(query)) {
5481
+ const confirmed = window.confirm(
5482
+ "This query uses advanced features (e.g. joins, calculated fields, grouping, sorting, pagination, time series) that Guided mode may not fully represent. The query will be preserved but some settings may not be editable in Guided mode.\n\nSwitch to Guided mode?"
5483
+ );
5484
+ if (!confirmed) return;
5485
+ }
5486
+ setDataSourceMode(newMode);
5487
+ }, [dataSourceMode, query, queryHasAdvancedFeatures]);
5355
5488
  const handleSavedQuerySelect = react.useCallback((savedQuery) => {
5356
5489
  setQuery(savedQuery.query);
5357
5490
  }, []);
@@ -5363,19 +5496,25 @@ function WidgetEditorPage({
5363
5496
  setPreviewResult(null);
5364
5497
  setPreviewError(null);
5365
5498
  }, []);
5499
+ const handleApplySql = react.useCallback((sql) => {
5500
+ setRawSql(sql);
5501
+ }, []);
5366
5502
  const handleSave = react.useCallback(() => {
5503
+ const savedConfig = { ...config, data_source_mode: dataSourceMode };
5504
+ if (dataSourceMode === "sql") {
5505
+ savedConfig.raw_sql = rawSql.trim() || void 0;
5506
+ }
5367
5507
  const savedWidget = {
5368
5508
  id: widget?.id ?? generateId(),
5369
5509
  type,
5370
5510
  title,
5371
- config,
5372
- query,
5511
+ config: savedConfig,
5512
+ query: dataSourceMode === "sql" ? null : query,
5373
5513
  position,
5374
- hyperlink,
5375
- dataSourceMode
5514
+ hyperlink
5376
5515
  };
5377
5516
  onSave(savedWidget);
5378
- }, [widget, type, title, config, query, position, hyperlink, dataSourceMode, onSave]);
5517
+ }, [widget, type, title, config, query, rawSql, position, hyperlink, dataSourceMode, onSave]);
5379
5518
  const columnSelectOptions = react.useMemo(() => {
5380
5519
  if (!schema) return [];
5381
5520
  return schema.tables.flatMap(
@@ -5398,7 +5537,8 @@ function WidgetEditorPage({
5398
5537
  justifyContent: "space-between",
5399
5538
  padding: `${theme.spacing.md} ${theme.spacing.lg}`,
5400
5539
  borderBottom: `1px solid ${theme.colors.border}`,
5401
- backgroundColor: theme.colors.surface
5540
+ backgroundColor: theme.colors.surface,
5541
+ flexShrink: 0
5402
5542
  };
5403
5543
  const headerLeftStyle = {
5404
5544
  display: "flex",
@@ -5429,38 +5569,28 @@ function WidgetEditorPage({
5429
5569
  };
5430
5570
  const bodyStyle = {
5431
5571
  flex: 1,
5432
- display: "flex",
5433
- minHeight: 0
5572
+ overflow: "auto",
5573
+ display: "grid",
5574
+ gridTemplateColumns: "360px 1fr"
5434
5575
  };
5435
5576
  const leftPanelStyle = {
5436
- width: "320px",
5437
- flexShrink: 0,
5438
5577
  borderRight: `1px solid ${theme.colors.border}`,
5439
- overflow: "auto",
5440
5578
  padding: theme.spacing.md,
5579
+ paddingBottom: theme.spacing.xl,
5441
5580
  display: "flex",
5442
5581
  flexDirection: "column",
5443
5582
  gap: theme.spacing.lg
5444
5583
  };
5445
5584
  const mainPanelStyle = {
5446
- flex: 1,
5447
- display: "flex",
5448
- flexDirection: "column",
5449
- minHeight: 0
5585
+ minWidth: 0
5450
5586
  };
5451
5587
  const previewPanelStyle = {
5452
- height: "300px",
5453
- flexShrink: 0,
5454
- padding: theme.spacing.md,
5455
- borderBottom: `1px solid ${theme.colors.border}`
5456
- };
5457
- const dataSourcePanelStyle = {
5458
- flex: "1 1 auto",
5459
- display: "flex",
5460
- flexDirection: "column",
5461
- minHeight: 0,
5588
+ height: "440px",
5589
+ padding: theme.spacing.lg,
5590
+ borderBottom: `1px solid ${theme.colors.border}`,
5462
5591
  overflow: "hidden"
5463
5592
  };
5593
+ const dataSourcePanelStyle = {};
5464
5594
  const dataSourceHeaderStyle = {
5465
5595
  display: "flex",
5466
5596
  alignItems: "center",
@@ -5480,15 +5610,12 @@ function WidgetEditorPage({
5480
5610
  transition: "all 0.15s ease"
5481
5611
  });
5482
5612
  const dataSourceContentStyle = {
5483
- flex: "1 1 auto",
5484
- overflow: "auto",
5485
5613
  padding: theme.spacing.md,
5486
- paddingBottom: "100px",
5487
- // Extra space to ensure filter buttons are visible
5488
- minHeight: "250px"
5614
+ paddingBottom: "200px"
5615
+ // Extra padding to create scroll room for filters
5489
5616
  };
5490
5617
  const sectionStyle = {
5491
- marginBottom: theme.spacing.md
5618
+ // Note: Parent has flex gap for spacing between sections
5492
5619
  };
5493
5620
  const sectionTitleStyle = {
5494
5621
  fontSize: theme.fontSizes.xs,
@@ -5537,7 +5664,7 @@ function WidgetEditorPage({
5537
5664
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
5538
5665
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "X-Axis Column" }),
5539
5666
  /* @__PURE__ */ jsxRuntime.jsx(
5540
- chunkNY6TZLST_cjs.Select,
5667
+ chunkPG7QBH3G_cjs.Select,
5541
5668
  {
5542
5669
  value: config.x_axis || "",
5543
5670
  onChange: (value) => updateConfig("x_axis", value || void 0),
@@ -5598,7 +5725,7 @@ function WidgetEditorPage({
5598
5725
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
5599
5726
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "X-Axis Column" }),
5600
5727
  /* @__PURE__ */ jsxRuntime.jsx(
5601
- chunkNY6TZLST_cjs.Select,
5728
+ chunkPG7QBH3G_cjs.Select,
5602
5729
  {
5603
5730
  value: config.x_axis || "",
5604
5731
  onChange: (value) => updateConfig("x_axis", value || void 0),
@@ -5679,7 +5806,7 @@ function WidgetEditorPage({
5679
5806
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
5680
5807
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "X-Axis Column" }),
5681
5808
  /* @__PURE__ */ jsxRuntime.jsx(
5682
- chunkNY6TZLST_cjs.Select,
5809
+ chunkPG7QBH3G_cjs.Select,
5683
5810
  {
5684
5811
  value: config.x_axis || "",
5685
5812
  onChange: (value) => updateConfig("x_axis", value || void 0),
@@ -5690,7 +5817,7 @@ function WidgetEditorPage({
5690
5817
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
5691
5818
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Y-Axis Column" }),
5692
5819
  /* @__PURE__ */ jsxRuntime.jsx(
5693
- chunkNY6TZLST_cjs.Select,
5820
+ chunkPG7QBH3G_cjs.Select,
5694
5821
  {
5695
5822
  value: config.y_axis?.[0] || "",
5696
5823
  onChange: (value) => updateConfig("y_axis", value ? [value] : void 0),
@@ -5723,7 +5850,7 @@ function WidgetEditorPage({
5723
5850
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
5724
5851
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Page Size" }),
5725
5852
  /* @__PURE__ */ jsxRuntime.jsx(
5726
- chunkNY6TZLST_cjs.Select,
5853
+ chunkPG7QBH3G_cjs.Select,
5727
5854
  {
5728
5855
  value: String(config.page_size || 10),
5729
5856
  onChange: (value) => updateConfig("page_size", parseInt(value, 10)),
@@ -5737,7 +5864,7 @@ function WidgetEditorPage({
5737
5864
  )
5738
5865
  ] }),
5739
5866
  /* @__PURE__ */ jsxRuntime.jsx(
5740
- chunkNY6TZLST_cjs.Checkbox,
5867
+ chunkPG7QBH3G_cjs.Checkbox,
5741
5868
  {
5742
5869
  label: "Sortable Columns",
5743
5870
  checked: config.sortable ?? true,
@@ -5795,10 +5922,10 @@ function WidgetEditorPage({
5795
5922
  },
5796
5923
  children: [
5797
5924
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: theme.spacing.sm }, children: [
5798
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "table", size: 16 }),
5925
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "table", size: 16 }),
5799
5926
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 500, color: theme.colors.text }, children: "Query configured" })
5800
5927
  ] }),
5801
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Button, { variant: "ghost", size: "sm", onClick: handleClearQuery, children: /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "x", size: 16 }) })
5928
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Button, { variant: "ghost", size: "sm", onClick: handleClearQuery, children: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "x", size: 16 }) })
5802
5929
  ]
5803
5930
  }
5804
5931
  ),
@@ -5817,14 +5944,14 @@ function WidgetEditorPage({
5817
5944
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: headerStyle, children: [
5818
5945
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: headerLeftStyle, children: [
5819
5946
  /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", style: backButtonStyle, onClick: onCancel, children: [
5820
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "chevron-left", size: 16 }),
5947
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "chevron-left", size: 16 }),
5821
5948
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Back" })
5822
5949
  ] }),
5823
5950
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: headerTitleStyle, children: isNew ? "Add Widget" : "Edit Widget" })
5824
5951
  ] }),
5825
5952
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: headerActionsStyle, children: [
5826
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Button, { variant: "ghost", onClick: onCancel, children: "Cancel" }),
5827
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Button, { variant: "primary", onClick: handleSave, children: isNew ? "Add Widget" : "Save Changes" })
5953
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Button, { variant: "ghost", onClick: onCancel, children: "Cancel" }),
5954
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Button, { variant: "primary", onClick: handleSave, children: isNew ? "Add Widget" : "Save Changes" })
5828
5955
  ] })
5829
5956
  ] }),
5830
5957
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: bodyStyle, children: [
@@ -5835,7 +5962,7 @@ function WidgetEditorPage({
5835
5962
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
5836
5963
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Title" }),
5837
5964
  /* @__PURE__ */ jsxRuntime.jsx(
5838
- chunkNY6TZLST_cjs.Input,
5965
+ chunkPG7QBH3G_cjs.Input,
5839
5966
  {
5840
5967
  value: title,
5841
5968
  onChange: (e) => setTitle(e.target.value),
@@ -5873,6 +6000,7 @@ function WidgetEditorPage({
5873
6000
  title,
5874
6001
  config,
5875
6002
  query,
6003
+ rawSql: dataSourceMode === "sql" ? rawSql : void 0,
5876
6004
  result: previewResult,
5877
6005
  isLoading: previewLoading,
5878
6006
  error: previewError
@@ -5882,30 +6010,57 @@ function WidgetEditorPage({
5882
6010
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: dataSourceHeaderStyle, children: [
5883
6011
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: theme.fontSizes.sm, fontWeight: 500, marginRight: "auto" }, children: "Data Source" }),
5884
6012
  /* @__PURE__ */ jsxRuntime.jsx(
5885
- "button",
6013
+ chunkPG7QBH3G_cjs.Tooltip,
5886
6014
  {
5887
- type: "button",
5888
- style: tabStyle(dataSourceMode === "guided"),
5889
- onClick: () => setDataSourceMode("guided"),
5890
- children: "Guided"
6015
+ content: "Quick setup: pick columns from dropdowns to build your chart",
6016
+ position: "bottom",
6017
+ style: { whiteSpace: "normal" },
6018
+ children: /* @__PURE__ */ jsxRuntime.jsx(
6019
+ "button",
6020
+ {
6021
+ type: "button",
6022
+ "data-testid": "data-source-mode-guided",
6023
+ style: tabStyle(dataSourceMode === "guided"),
6024
+ onClick: () => handleModeSwitch("guided"),
6025
+ children: "Guided"
6026
+ }
6027
+ )
5891
6028
  }
5892
6029
  ),
5893
6030
  /* @__PURE__ */ jsxRuntime.jsx(
5894
- "button",
6031
+ chunkPG7QBH3G_cjs.Tooltip,
5895
6032
  {
5896
- type: "button",
5897
- style: tabStyle(dataSourceMode === "advanced"),
5898
- onClick: () => setDataSourceMode("advanced"),
5899
- children: "Advanced"
6033
+ content: "Full control: combine tables, add filters, and create custom calculations",
6034
+ position: "bottom",
6035
+ style: { whiteSpace: "normal" },
6036
+ children: /* @__PURE__ */ jsxRuntime.jsx(
6037
+ "button",
6038
+ {
6039
+ type: "button",
6040
+ "data-testid": "data-source-mode-advanced",
6041
+ style: tabStyle(dataSourceMode === "advanced"),
6042
+ onClick: () => handleModeSwitch("advanced"),
6043
+ children: "Advanced"
6044
+ }
6045
+ )
5900
6046
  }
5901
6047
  ),
5902
6048
  /* @__PURE__ */ jsxRuntime.jsx(
5903
- "button",
6049
+ chunkPG7QBH3G_cjs.Tooltip,
5904
6050
  {
5905
- type: "button",
5906
- style: tabStyle(dataSourceMode === "saved"),
5907
- onClick: () => setDataSourceMode("saved"),
5908
- children: "Saved Query"
6051
+ content: "Write raw SQL queries directly, with optional AI assistance",
6052
+ position: "bottom",
6053
+ style: { whiteSpace: "normal" },
6054
+ children: /* @__PURE__ */ jsxRuntime.jsx(
6055
+ "button",
6056
+ {
6057
+ type: "button",
6058
+ "data-testid": "data-source-mode-sql",
6059
+ style: tabStyle(dataSourceMode === "sql"),
6060
+ onClick: () => handleModeSwitch("sql"),
6061
+ children: "SQL"
6062
+ }
6063
+ )
5909
6064
  }
5910
6065
  )
5911
6066
  ] }),
@@ -5921,7 +6076,7 @@ function WidgetEditorPage({
5921
6076
  }
5922
6077
  ),
5923
6078
  dataSourceMode === "advanced" && /* @__PURE__ */ jsxRuntime.jsx(
5924
- chunkNY6TZLST_cjs.QueryBuilder,
6079
+ chunkPG7QBH3G_cjs.QueryBuilder,
5925
6080
  {
5926
6081
  initialQuery: query ?? void 0,
5927
6082
  onQueryChange: handleQueryChange,
@@ -5932,13 +6087,106 @@ function WidgetEditorPage({
5932
6087
  }
5933
6088
  ),
5934
6089
  dataSourceMode === "saved" && /* @__PURE__ */ jsxRuntime.jsx(
5935
- chunkNY6TZLST_cjs.SavedQueryPicker,
6090
+ chunkPG7QBH3G_cjs.SavedQueryPicker,
5936
6091
  {
5937
6092
  currentQuery: query,
5938
6093
  onSelect: handleSavedQuerySelect,
5939
6094
  showSave: false
5940
6095
  }
5941
- )
6096
+ ),
6097
+ dataSourceMode === "sql" && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: 0, height: "100%", minHeight: "400px" }, children: [
6098
+ /* @__PURE__ */ jsxRuntime.jsx("div", { "data-testid": "schema-panel", style: {
6099
+ width: schemaOpen ? "220px" : "36px",
6100
+ flexShrink: 0,
6101
+ transition: "width 0.2s ease",
6102
+ borderRight: `1px solid ${theme.colors.border}`,
6103
+ display: "flex",
6104
+ flexDirection: "column",
6105
+ overflow: "hidden"
6106
+ }, children: schemaOpen ? /* @__PURE__ */ jsxRuntime.jsx(
6107
+ chunkPG7QBH3G_cjs.SchemaExplorer,
6108
+ {
6109
+ searchable: true,
6110
+ collapsible: true,
6111
+ onColumnSelect: (table, col) => {
6112
+ const ref = `"${table.name}"."${col.name}"`;
6113
+ setRawSql((prev) => prev ? `${prev} ${ref}` : ref);
6114
+ },
6115
+ headerAction: /* @__PURE__ */ jsxRuntime.jsx(
6116
+ "button",
6117
+ {
6118
+ type: "button",
6119
+ onClick: () => setSchemaOpen(false),
6120
+ title: "Collapse schema panel",
6121
+ "data-testid": "schema-toggle-open",
6122
+ style: {
6123
+ display: "flex",
6124
+ alignItems: "center",
6125
+ justifyContent: "center",
6126
+ width: "22px",
6127
+ height: "22px",
6128
+ backgroundColor: "transparent",
6129
+ border: `1px solid ${theme.colors.border}`,
6130
+ borderRadius: theme.radius.sm,
6131
+ cursor: "pointer",
6132
+ color: theme.colors.textMuted,
6133
+ flexShrink: 0
6134
+ },
6135
+ children: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "chevron-left", size: 12 })
6136
+ }
6137
+ ),
6138
+ style: { flex: 1, border: "none", borderRadius: 0 }
6139
+ }
6140
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
6141
+ "button",
6142
+ {
6143
+ type: "button",
6144
+ onClick: () => setSchemaOpen(true),
6145
+ title: "Show schema browser",
6146
+ "data-testid": "schema-toggle-collapsed",
6147
+ style: {
6148
+ display: "flex",
6149
+ flexDirection: "column",
6150
+ alignItems: "center",
6151
+ gap: "6px",
6152
+ paddingTop: theme.spacing.sm,
6153
+ width: "100%",
6154
+ height: "100%",
6155
+ backgroundColor: theme.colors.surface,
6156
+ border: "none",
6157
+ cursor: "pointer",
6158
+ color: theme.colors.textMuted,
6159
+ fontFamily: theme.fonts.sans
6160
+ },
6161
+ children: [
6162
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "table", size: 16 }),
6163
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: {
6164
+ writingMode: "vertical-rl",
6165
+ fontSize: "11px",
6166
+ fontWeight: 500,
6167
+ letterSpacing: "0.04em"
6168
+ }, children: "Schema" })
6169
+ ]
6170
+ }
6171
+ ) }),
6172
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, minWidth: 0 }, "data-testid": "sql-editor", children: /* @__PURE__ */ jsxRuntime.jsx(
6173
+ chunkPG7QBH3G_cjs.CustomSQLEditor,
6174
+ {
6175
+ initialSql: rawSql,
6176
+ onSqlChange: setRawSql,
6177
+ onExecute: () => void refreshPreview(),
6178
+ showResults: false,
6179
+ placeholder: "Write your SQL query here..."
6180
+ }
6181
+ ) }),
6182
+ !llmStatusLoading && llmEnabled && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: "340px", flexShrink: 0 }, "data-testid": "chat-panel", children: /* @__PURE__ */ jsxRuntime.jsx(
6183
+ chunkPG7QBH3G_cjs.ChatPanel,
6184
+ {
6185
+ currentSql: rawSql || null,
6186
+ onApplySql: handleApplySql
6187
+ }
6188
+ ) })
6189
+ ] })
5942
6190
  ] })
5943
6191
  ] })
5944
6192
  ] })
@@ -5982,8 +6230,8 @@ function DashboardEditor({
5982
6230
  className = ""
5983
6231
  }) {
5984
6232
  const { theme } = chunkLMTG3LRC_cjs.useTheme();
5985
- const { client } = chunkNY6TZLST_cjs.useAnalytics();
5986
- const { schema } = chunkNY6TZLST_cjs.useSchema();
6233
+ const { client } = chunkPG7QBH3G_cjs.useAnalytics();
6234
+ const { schema } = chunkPG7QBH3G_cjs.useSchema();
5987
6235
  const [currentDashboardId, setCurrentDashboardId] = react.useState(dashboardId);
5988
6236
  react.useEffect(() => {
5989
6237
  setCurrentDashboardId(dashboardId);
@@ -6020,7 +6268,9 @@ function DashboardEditor({
6020
6268
  clientRef.current = client;
6021
6269
  const loadedDashboardRef = react.useRef(null);
6022
6270
  const executeWidgetQueries = react.useCallback(async (widgets, currentClient) => {
6023
- const widgetsWithQueries = widgets.filter((w) => w.query);
6271
+ const widgetsWithQueries = widgets.filter(
6272
+ (w) => w.query || w.config?.data_source_mode === "sql" && w.config?.raw_sql
6273
+ );
6024
6274
  if (widgetsWithQueries.length === 0) return;
6025
6275
  for (let i = 0; i < widgetsWithQueries.length; i += batchSize) {
6026
6276
  const batch = widgetsWithQueries.slice(i, i + batchSize);
@@ -6034,7 +6284,8 @@ function DashboardEditor({
6034
6284
  await Promise.all(
6035
6285
  batch.map(async (widget) => {
6036
6286
  try {
6037
- const result = await currentClient.executeQuery(widget.query);
6287
+ const isSqlMode = widget.config?.data_source_mode === "sql" && widget.config?.raw_sql;
6288
+ const result = isSqlMode ? await currentClient.executeSQL(widget.config.raw_sql) : await currentClient.executeQuery(widget.query);
6038
6289
  setWidgetResults((prev) => ({ ...prev, [widget.id]: result }));
6039
6290
  setWidgetRefreshTimes((prev) => ({ ...prev, [widget.id]: Math.floor(Date.now() / 1e3) }));
6040
6291
  } catch (err) {
@@ -6111,11 +6362,12 @@ function DashboardEditor({
6111
6362
  const refreshWidget = react.useCallback(
6112
6363
  async (widgetId, widgetOverride) => {
6113
6364
  const widget = widgetOverride ?? dashboard.widgets.find((w) => w.id === widgetId);
6114
- if (!widget?.query || !client) return;
6365
+ const isSqlMode = widget?.config?.data_source_mode === "sql" && widget?.config?.raw_sql;
6366
+ if (!widget?.query && !isSqlMode || !client) return;
6115
6367
  setWidgetLoading((prev) => ({ ...prev, [widgetId]: true }));
6116
6368
  setRefreshingWidgets((prev) => new Set(prev).add(widgetId));
6117
6369
  try {
6118
- const result = await client.executeQuery(widget.query, true);
6370
+ const result = isSqlMode ? await client.executeSQL(widget.config.raw_sql) : await client.executeQuery(widget.query, true);
6119
6371
  setWidgetResults((prev) => ({ ...prev, [widgetId]: result }));
6120
6372
  setWidgetRefreshTimes((prev) => ({ ...prev, [widgetId]: Math.floor(Date.now() / 1e3) }));
6121
6373
  setWidgetErrors((prev) => {
@@ -6610,7 +6862,7 @@ function WidgetPalette({
6610
6862
  Object.assign(e.currentTarget.style, itemStyle);
6611
6863
  },
6612
6864
  children: [
6613
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: iconContainerStyle, children: /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: widgetType.icon, size: 24 }) }),
6865
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: iconContainerStyle, children: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: widgetType.icon, size: 24 }) }),
6614
6866
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: labelStyle, children: widgetType.label }),
6615
6867
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: descriptionStyle, children: widgetType.description })
6616
6868
  ]
@@ -6762,7 +7014,7 @@ function WidgetEditor({
6762
7014
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
6763
7015
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Format" }),
6764
7016
  /* @__PURE__ */ jsxRuntime.jsx(
6765
- chunkNY6TZLST_cjs.Select,
7017
+ chunkPG7QBH3G_cjs.Select,
6766
7018
  {
6767
7019
  value: config.format || "number",
6768
7020
  onChange: (value) => updateConfig("format", value),
@@ -6778,7 +7030,7 @@ function WidgetEditor({
6778
7030
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
6779
7031
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Trend Comparison Field" }),
6780
7032
  /* @__PURE__ */ jsxRuntime.jsx(
6781
- chunkNY6TZLST_cjs.Select,
7033
+ chunkPG7QBH3G_cjs.Select,
6782
7034
  {
6783
7035
  value: config.trend_comparison || "",
6784
7036
  onChange: (value) => updateConfig("trend_comparison", value || void 0),
@@ -6795,7 +7047,7 @@ function WidgetEditor({
6795
7047
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
6796
7048
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "X-Axis Column" }),
6797
7049
  /* @__PURE__ */ jsxRuntime.jsx(
6798
- chunkNY6TZLST_cjs.Select,
7050
+ chunkPG7QBH3G_cjs.Select,
6799
7051
  {
6800
7052
  value: config.x_axis || "",
6801
7053
  onChange: (value) => updateConfig("x_axis", value),
@@ -6806,7 +7058,7 @@ function WidgetEditor({
6806
7058
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
6807
7059
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Orientation" }),
6808
7060
  /* @__PURE__ */ jsxRuntime.jsx(
6809
- chunkNY6TZLST_cjs.Select,
7061
+ chunkPG7QBH3G_cjs.Select,
6810
7062
  {
6811
7063
  value: config.orientation || "vertical",
6812
7064
  onChange: (value) => updateConfig("orientation", value),
@@ -6819,7 +7071,7 @@ function WidgetEditor({
6819
7071
  ] }),
6820
7072
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: rowStyle, children: [
6821
7073
  /* @__PURE__ */ jsxRuntime.jsx(
6822
- chunkNY6TZLST_cjs.Checkbox,
7074
+ chunkPG7QBH3G_cjs.Checkbox,
6823
7075
  {
6824
7076
  label: "Show Legend",
6825
7077
  checked: config.show_legend ?? true,
@@ -6827,7 +7079,7 @@ function WidgetEditor({
6827
7079
  }
6828
7080
  ),
6829
7081
  /* @__PURE__ */ jsxRuntime.jsx(
6830
- chunkNY6TZLST_cjs.Checkbox,
7082
+ chunkPG7QBH3G_cjs.Checkbox,
6831
7083
  {
6832
7084
  label: "Stacked",
6833
7085
  checked: config.stacked ?? false,
@@ -6835,7 +7087,7 @@ function WidgetEditor({
6835
7087
  }
6836
7088
  ),
6837
7089
  /* @__PURE__ */ jsxRuntime.jsx(
6838
- chunkNY6TZLST_cjs.Checkbox,
7090
+ chunkPG7QBH3G_cjs.Checkbox,
6839
7091
  {
6840
7092
  label: "Show Data Labels",
6841
7093
  checked: config.show_data_labels ?? false,
@@ -6850,7 +7102,7 @@ function WidgetEditor({
6850
7102
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
6851
7103
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "X-Axis Column" }),
6852
7104
  /* @__PURE__ */ jsxRuntime.jsx(
6853
- chunkNY6TZLST_cjs.Select,
7105
+ chunkPG7QBH3G_cjs.Select,
6854
7106
  {
6855
7107
  value: config.x_axis || "",
6856
7108
  onChange: (value) => updateConfig("x_axis", value),
@@ -6860,7 +7112,7 @@ function WidgetEditor({
6860
7112
  ] }),
6861
7113
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: rowStyle, children: [
6862
7114
  /* @__PURE__ */ jsxRuntime.jsx(
6863
- chunkNY6TZLST_cjs.Checkbox,
7115
+ chunkPG7QBH3G_cjs.Checkbox,
6864
7116
  {
6865
7117
  label: "Show Legend",
6866
7118
  checked: config.show_legend ?? true,
@@ -6868,7 +7120,7 @@ function WidgetEditor({
6868
7120
  }
6869
7121
  ),
6870
7122
  /* @__PURE__ */ jsxRuntime.jsx(
6871
- chunkNY6TZLST_cjs.Checkbox,
7123
+ chunkPG7QBH3G_cjs.Checkbox,
6872
7124
  {
6873
7125
  label: "Show Data Labels",
6874
7126
  checked: config.show_data_labels ?? false,
@@ -6880,7 +7132,7 @@ function WidgetEditor({
6880
7132
  case "pie_chart":
6881
7133
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: rowStyle, children: [
6882
7134
  /* @__PURE__ */ jsxRuntime.jsx(
6883
- chunkNY6TZLST_cjs.Checkbox,
7135
+ chunkPG7QBH3G_cjs.Checkbox,
6884
7136
  {
6885
7137
  label: "Show Legend",
6886
7138
  checked: config.show_legend ?? true,
@@ -6888,7 +7140,7 @@ function WidgetEditor({
6888
7140
  }
6889
7141
  ),
6890
7142
  /* @__PURE__ */ jsxRuntime.jsx(
6891
- chunkNY6TZLST_cjs.Checkbox,
7143
+ chunkPG7QBH3G_cjs.Checkbox,
6892
7144
  {
6893
7145
  label: "Show Data Labels",
6894
7146
  checked: config.show_data_labels ?? true,
@@ -6901,7 +7153,7 @@ function WidgetEditor({
6901
7153
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
6902
7154
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Page Size" }),
6903
7155
  /* @__PURE__ */ jsxRuntime.jsx(
6904
- chunkNY6TZLST_cjs.Select,
7156
+ chunkPG7QBH3G_cjs.Select,
6905
7157
  {
6906
7158
  value: String(config.page_size || 10),
6907
7159
  onChange: (value) => updateConfig("page_size", parseInt(value, 10)),
@@ -6916,7 +7168,7 @@ function WidgetEditor({
6916
7168
  )
6917
7169
  ] }),
6918
7170
  /* @__PURE__ */ jsxRuntime.jsx(
6919
- chunkNY6TZLST_cjs.Checkbox,
7171
+ chunkPG7QBH3G_cjs.Checkbox,
6920
7172
  {
6921
7173
  label: "Sortable Columns",
6922
7174
  checked: config.sortable ?? true,
@@ -6949,7 +7201,7 @@ function WidgetEditor({
6949
7201
  )
6950
7202
  ] }),
6951
7203
  /* @__PURE__ */ jsxRuntime.jsx(
6952
- chunkNY6TZLST_cjs.Checkbox,
7204
+ chunkPG7QBH3G_cjs.Checkbox,
6953
7205
  {
6954
7206
  label: "Enable Markdown",
6955
7207
  checked: config.markdown ?? true,
@@ -6964,7 +7216,7 @@ function WidgetEditor({
6964
7216
  return /* @__PURE__ */ jsxRuntime.jsx("div", { style: overlayStyle, onClick: onCancel, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: modalStyle, onClick: (e) => e.stopPropagation(), children: [
6965
7217
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: headerStyle, children: [
6966
7218
  /* @__PURE__ */ jsxRuntime.jsx("h2", { style: titleStyle, children: "Edit Widget" }),
6967
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Button, { variant: "ghost", size: "sm", onClick: onCancel, children: /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "x", size: 20 }) })
7219
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Button, { variant: "ghost", size: "sm", onClick: onCancel, children: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "x", size: 20 }) })
6968
7220
  ] }),
6969
7221
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: bodyStyle, children: [
6970
7222
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: sectionStyle, children: [
@@ -6972,7 +7224,7 @@ function WidgetEditor({
6972
7224
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyle, children: [
6973
7225
  /* @__PURE__ */ jsxRuntime.jsx("label", { style: labelStyle, children: "Title" }),
6974
7226
  /* @__PURE__ */ jsxRuntime.jsx(
6975
- chunkNY6TZLST_cjs.Input,
7227
+ chunkPG7QBH3G_cjs.Input,
6976
7228
  {
6977
7229
  value: title,
6978
7230
  onChange: (e) => setTitle(e.target.value),
@@ -7008,10 +7260,10 @@ function WidgetEditor({
7008
7260
  },
7009
7261
  children: [
7010
7262
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: theme.spacing.sm }, children: [
7011
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "table", size: 16 }),
7263
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "table", size: 16 }),
7012
7264
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 500, color: theme.colors.text }, children: queryName || "Custom Query" })
7013
7265
  ] }),
7014
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Button, { variant: "ghost", size: "sm", onClick: handleClearQuery, children: /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "x", size: 16 }) })
7266
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Button, { variant: "ghost", size: "sm", onClick: handleClearQuery, children: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "x", size: 16 }) })
7015
7267
  ]
7016
7268
  }
7017
7269
  ),
@@ -7039,11 +7291,11 @@ function WidgetEditor({
7039
7291
  },
7040
7292
  children: [
7041
7293
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", color: theme.colors.textMuted }, children: [
7042
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "table", size: 24, style: { marginBottom: theme.spacing.xs } }),
7294
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "table", size: 24, style: { marginBottom: theme.spacing.xs } }),
7043
7295
  /* @__PURE__ */ jsxRuntime.jsx("div", { children: "Select a saved query to power this widget" })
7044
7296
  ] }),
7045
7297
  /* @__PURE__ */ jsxRuntime.jsx(
7046
- chunkNY6TZLST_cjs.SavedQueryPicker,
7298
+ chunkPG7QBH3G_cjs.SavedQueryPicker,
7047
7299
  {
7048
7300
  currentQuery: null,
7049
7301
  onSelect: handleSelectSavedQuery,
@@ -7056,8 +7308,8 @@ function WidgetEditor({
7056
7308
  ] })
7057
7309
  ] }),
7058
7310
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: footerStyle, children: [
7059
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Button, { variant: "ghost", onClick: onCancel, children: "Cancel" }),
7060
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Button, { variant: "primary", onClick: handleSave, children: "Save Widget" })
7311
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Button, { variant: "ghost", onClick: onCancel, children: "Cancel" }),
7312
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Button, { variant: "primary", onClick: handleSave, children: "Save Widget" })
7061
7313
  ] })
7062
7314
  ] }) });
7063
7315
  }
@@ -7202,31 +7454,31 @@ var DashboardCard = react.forwardRef(
7202
7454
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: headerStyles, children: [
7203
7455
  /* @__PURE__ */ jsxRuntime.jsx("h3", { style: titleStyles, children: dashboard.name }),
7204
7456
  actions ? actions : /* @__PURE__ */ jsxRuntime.jsxs(
7205
- chunkNY6TZLST_cjs.Dropdown,
7457
+ chunkPG7QBH3G_cjs.Dropdown,
7206
7458
  {
7207
7459
  trigger: /* @__PURE__ */ jsxRuntime.jsx(
7208
- chunkNY6TZLST_cjs.Button,
7460
+ chunkPG7QBH3G_cjs.Button,
7209
7461
  {
7210
7462
  variant: "ghost",
7211
7463
  size: "sm",
7212
7464
  onClick: (e) => e.stopPropagation(),
7213
7465
  disabled: actionsDisabled,
7214
7466
  "aria-label": "Dashboard actions",
7215
- children: /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "more-vertical", size: 16 })
7467
+ children: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "more-vertical", size: 16 })
7216
7468
  }
7217
7469
  ),
7218
7470
  children: [
7219
- /* @__PURE__ */ jsxRuntime.jsxs(chunkNY6TZLST_cjs.DropdownItem, { onClick: () => handleMenuAction("edit"), children: [
7220
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "edit", size: 14 }),
7471
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkPG7QBH3G_cjs.DropdownItem, { onClick: () => handleMenuAction("edit"), children: [
7472
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "edit", size: 14 }),
7221
7473
  "Edit"
7222
7474
  ] }),
7223
- /* @__PURE__ */ jsxRuntime.jsxs(chunkNY6TZLST_cjs.DropdownItem, { onClick: () => handleMenuAction("duplicate"), children: [
7224
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "copy", size: 14 }),
7475
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkPG7QBH3G_cjs.DropdownItem, { onClick: () => handleMenuAction("duplicate"), children: [
7476
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "copy", size: 14 }),
7225
7477
  "Duplicate"
7226
7478
  ] }),
7227
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.DropdownSeparator, {}),
7228
- /* @__PURE__ */ jsxRuntime.jsxs(chunkNY6TZLST_cjs.DropdownItem, { onClick: () => handleMenuAction("delete"), children: [
7229
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "trash", size: 14 }),
7479
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.DropdownSeparator, {}),
7480
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkPG7QBH3G_cjs.DropdownItem, { onClick: () => handleMenuAction("delete"), children: [
7481
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "trash", size: 14 }),
7230
7482
  "Delete"
7231
7483
  ] })
7232
7484
  ]
@@ -7236,13 +7488,13 @@ var DashboardCard = react.forwardRef(
7236
7488
  dashboard.description && /* @__PURE__ */ jsxRuntime.jsx("p", { style: descriptionStyles, children: dashboard.description }),
7237
7489
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: metaStyles, children: [
7238
7490
  /* @__PURE__ */ jsxRuntime.jsxs("span", { style: metaItemStyles, children: [
7239
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "grid", size: 12 }),
7491
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "grid", size: 12 }),
7240
7492
  dashboard.widgets.length,
7241
7493
  " widget",
7242
7494
  dashboard.widgets.length !== 1 ? "s" : ""
7243
7495
  ] }),
7244
7496
  /* @__PURE__ */ jsxRuntime.jsxs("span", { style: metaItemStyles, children: [
7245
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "calendar", size: 12 }),
7497
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "calendar", size: 12 }),
7246
7498
  formatDate(dashboard.updated_at)
7247
7499
  ] }),
7248
7500
  dashboard.is_public ? /* @__PURE__ */ jsxRuntime.jsx("span", { style: publicBadgeStyles, children: "Public" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: privateBadgeStyles, children: "Private" })
@@ -7300,32 +7552,32 @@ var DashboardList = react.forwardRef(
7300
7552
  if (isLoading) {
7301
7553
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, style: { ...containerStyles, ...style }, ...props, children: [
7302
7554
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: headerStyles2, children: [
7303
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Skeleton, { width: 200, height: 32 }),
7304
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Skeleton, { width: 150, height: 40 })
7555
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Skeleton, { width: 200, height: 32 }),
7556
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Skeleton, { width: 150, height: 40 })
7305
7557
  ] }),
7306
- /* @__PURE__ */ jsxRuntime.jsx("div", { style: getGridStyles(columns), children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Skeleton, { height: 150, style: { borderRadius: "var(--prismiq-radius-lg)" } }, i)) })
7558
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: getGridStyles(columns), children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Skeleton, { height: 150, style: { borderRadius: "var(--prismiq-radius-lg)" } }, i)) })
7307
7559
  ] });
7308
7560
  }
7309
7561
  if (error) {
7310
7562
  return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, style: { ...containerStyles, ...style }, ...props, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: errorStyles, children: [
7311
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "alert-circle", size: 48 }),
7563
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "alert-circle", size: 48 }),
7312
7564
  /* @__PURE__ */ jsxRuntime.jsxs("p", { children: [
7313
7565
  "Failed to load dashboards: ",
7314
7566
  error.message
7315
7567
  ] }),
7316
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Button, { variant: "secondary", onClick: () => window.location.reload(), children: "Retry" })
7568
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Button, { variant: "secondary", onClick: () => window.location.reload(), children: "Retry" })
7317
7569
  ] }) });
7318
7570
  }
7319
7571
  if (!dashboards || dashboards.length === 0) {
7320
7572
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref, style: { ...containerStyles, ...style }, ...props, children: [
7321
7573
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: headerStyles2, children: [
7322
7574
  /* @__PURE__ */ jsxRuntime.jsx("h2", { style: titleStyles2, children: "Dashboards" }),
7323
- onCreate && /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Button, { onClick: onCreate, leftIcon: /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "plus", size: 16 }), children: "Create Dashboard" })
7575
+ onCreate && /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Button, { onClick: onCreate, leftIcon: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "plus", size: 16 }), children: "Create Dashboard" })
7324
7576
  ] }),
7325
7577
  emptyState || /* @__PURE__ */ jsxRuntime.jsx(
7326
- chunkNY6TZLST_cjs.EmptyState,
7578
+ chunkPG7QBH3G_cjs.EmptyState,
7327
7579
  {
7328
- icon: /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "layout", size: 64 }),
7580
+ icon: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "layout", size: 64 }),
7329
7581
  title: "No dashboards yet",
7330
7582
  description: "Create your first dashboard to start visualizing your data.",
7331
7583
  action: onCreate ? { label: "Create Dashboard", onClick: onCreate } : void 0
@@ -7340,7 +7592,7 @@ var DashboardList = react.forwardRef(
7340
7592
  dashboards.length,
7341
7593
  ")"
7342
7594
  ] }),
7343
- onCreate && /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Button, { onClick: onCreate, leftIcon: /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Icon, { name: "plus", size: 16 }), children: "Create Dashboard" })
7595
+ onCreate && /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Button, { onClick: onCreate, leftIcon: /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Icon, { name: "plus", size: 16 }), children: "Create Dashboard" })
7344
7596
  ] }),
7345
7597
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: getGridStyles(columns), children: dashboards.map((dashboard) => {
7346
7598
  const cardProps = {
@@ -7440,7 +7692,7 @@ var DashboardDialog = react.forwardRef(
7440
7692
  );
7441
7693
  const displayError = validationError || error;
7442
7694
  return /* @__PURE__ */ jsxRuntime.jsx(
7443
- chunkNY6TZLST_cjs.Dialog,
7695
+ chunkPG7QBH3G_cjs.Dialog,
7444
7696
  {
7445
7697
  open,
7446
7698
  onClose,
@@ -7452,7 +7704,7 @@ var DashboardDialog = react.forwardRef(
7452
7704
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyles, children: [
7453
7705
  /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "dashboard-name", style: labelStyles, children: "Name" }),
7454
7706
  /* @__PURE__ */ jsxRuntime.jsx(
7455
- chunkNY6TZLST_cjs.Input,
7707
+ chunkPG7QBH3G_cjs.Input,
7456
7708
  {
7457
7709
  id: "dashboard-name",
7458
7710
  value: formState.name,
@@ -7466,7 +7718,7 @@ var DashboardDialog = react.forwardRef(
7466
7718
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: fieldStyles, children: [
7467
7719
  /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "dashboard-description", style: labelStyles, children: "Description (optional)" }),
7468
7720
  /* @__PURE__ */ jsxRuntime.jsx(
7469
- chunkNY6TZLST_cjs.Input,
7721
+ chunkPG7QBH3G_cjs.Input,
7470
7722
  {
7471
7723
  id: "dashboard-description",
7472
7724
  value: formState.description,
@@ -7478,7 +7730,7 @@ var DashboardDialog = react.forwardRef(
7478
7730
  ] }),
7479
7731
  /* @__PURE__ */ jsxRuntime.jsxs("div", { style: checkboxContainerStyles, children: [
7480
7732
  /* @__PURE__ */ jsxRuntime.jsx(
7481
- chunkNY6TZLST_cjs.Checkbox,
7733
+ chunkPG7QBH3G_cjs.Checkbox,
7482
7734
  {
7483
7735
  id: "dashboard-public",
7484
7736
  checked: formState.isPublic,
@@ -7488,9 +7740,9 @@ var DashboardDialog = react.forwardRef(
7488
7740
  ),
7489
7741
  /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: "dashboard-public", style: checkboxLabelStyles, children: "Make this dashboard public" })
7490
7742
  ] }),
7491
- /* @__PURE__ */ jsxRuntime.jsxs(chunkNY6TZLST_cjs.DialogFooter, { children: [
7743
+ /* @__PURE__ */ jsxRuntime.jsxs(chunkPG7QBH3G_cjs.DialogFooter, { children: [
7492
7744
  /* @__PURE__ */ jsxRuntime.jsx(
7493
- chunkNY6TZLST_cjs.Button,
7745
+ chunkPG7QBH3G_cjs.Button,
7494
7746
  {
7495
7747
  type: "button",
7496
7748
  variant: "secondary",
@@ -7499,7 +7751,7 @@ var DashboardDialog = react.forwardRef(
7499
7751
  children: "Cancel"
7500
7752
  }
7501
7753
  ),
7502
- /* @__PURE__ */ jsxRuntime.jsx(chunkNY6TZLST_cjs.Button, { type: "submit", loading: isLoading, children: isEditMode ? "Save Changes" : "Create Dashboard" })
7754
+ /* @__PURE__ */ jsxRuntime.jsx(chunkPG7QBH3G_cjs.Button, { type: "submit", loading: isLoading, children: isEditMode ? "Save Changes" : "Create Dashboard" })
7503
7755
  ] })
7504
7756
  ] })
7505
7757
  }
@@ -7539,5 +7791,5 @@ exports.useDashboardFilters = useDashboardFilters;
7539
7791
  exports.useFullscreen = useFullscreen;
7540
7792
  exports.useWidget = useWidget;
7541
7793
  exports.useWidgetVisibility = useWidgetVisibility;
7542
- //# sourceMappingURL=chunk-FEABEF3J.cjs.map
7543
- //# sourceMappingURL=chunk-FEABEF3J.cjs.map
7794
+ //# sourceMappingURL=chunk-FKXCINUF.cjs.map
7795
+ //# sourceMappingURL=chunk-FKXCINUF.cjs.map