@quillsql/react 2.16.49 → 2.16.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -37,6 +37,89 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
37
37
  mod
38
38
  ));
39
39
 
40
+ // src/utils/textProcessing.ts
41
+ function capitalize(text) {
42
+ return text.charAt(0).toUpperCase() + text.slice(1);
43
+ }
44
+ function matchCasing(text, template) {
45
+ if (!text || !template) {
46
+ return text ?? "";
47
+ }
48
+ const isTitleCase = (str) => /^[A-Z][a-z]*([A-Z][a-z]*)*$/.test(str);
49
+ const isCamelCase = (str) => /^[a-z]+([A-Z][a-z]*)*$/.test(str);
50
+ const isSnakeCase = (str) => /^[a-z0-9]+(_[a-z0-9]+)*$/.test(str);
51
+ const isAllLowerCase = (str) => /^[a-z]+$/.test(str);
52
+ const isAllUpperCase = (str) => /^[A-Z]+$/.test(str);
53
+ const isCapitalized = (str) => /^[A-Z][a-z]*$/.test(str);
54
+ const isScreamingSnakeCase = (str) => /^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$/.test(str);
55
+ const toTitleCase = (str) => str.toLowerCase().replace(/\b\w/g, (char) => char.toUpperCase());
56
+ const toCamelCase = (str) => str.replace(/_./g, (match) => match.charAt(1).toUpperCase()).toLowerCase();
57
+ const toSnakeCase = (str) => str.replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`);
58
+ const toLowerCase = (str) => str.toLowerCase();
59
+ const toUpperCase = (str) => str.toUpperCase();
60
+ const toCapitalized = (str) => str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
61
+ const toScreamingSnakeCase = (str) => str.replace(/([A-Z])/g, "_$1").replace(/^_/, "").toUpperCase();
62
+ if (isTitleCase(template)) {
63
+ return toTitleCase(text);
64
+ } else if (isCamelCase(template)) {
65
+ return toCamelCase(text);
66
+ } else if (isSnakeCase(template)) {
67
+ return toSnakeCase(text);
68
+ } else if (isAllLowerCase(template)) {
69
+ return toLowerCase(text);
70
+ } else if (isAllUpperCase(template)) {
71
+ return toUpperCase(text);
72
+ } else if (isCapitalized(template)) {
73
+ return toCapitalized(text);
74
+ } else if (isScreamingSnakeCase(template)) {
75
+ return toScreamingSnakeCase(text);
76
+ } else {
77
+ return text;
78
+ }
79
+ }
80
+ function snakeCaseToTitleCase(str) {
81
+ if (!str) {
82
+ return str;
83
+ }
84
+ return str.toString().split(/_| /).map(
85
+ (word) => word === "id" ? "ID" : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
86
+ ).join(" ");
87
+ }
88
+ function snakeAndCamelCaseToTitleCase(str) {
89
+ if (!str || typeof str !== "string") {
90
+ return str;
91
+ }
92
+ if (str.includes("_")) {
93
+ return str.split(/_| /).map((word) => word === "id" ? "ID" : capitalize(word)).join(" ");
94
+ } else {
95
+ const text = str.replace(/([a-z])([A-Z])/g, "$1 $2");
96
+ const newText = text.split(" ").map((word) => word === "Id" || word === "id" ? "ID" : capitalize(word)).join(" ");
97
+ return newText;
98
+ }
99
+ }
100
+ function formatIdentifierLabel(str) {
101
+ if (!str || typeof str !== "string") {
102
+ return str;
103
+ }
104
+ const hasUnderscore = str.includes("_");
105
+ const hasCamelCaseBoundary = /[a-z0-9][A-Z]/.test(str);
106
+ if (hasUnderscore || hasCamelCaseBoundary) {
107
+ return snakeAndCamelCaseToTitleCase(str);
108
+ }
109
+ return str;
110
+ }
111
+ function removeDoubleQuotes(str) {
112
+ if (!str) {
113
+ return str;
114
+ }
115
+ return str.replace(/"/g, "");
116
+ }
117
+ var init_textProcessing = __esm({
118
+ "src/utils/textProcessing.ts"() {
119
+ "use strict";
120
+ }
121
+ });
122
+
40
123
  // src/utils/valueFormatter.ts
41
124
  import {
42
125
  endOfWeek,
@@ -73,6 +156,7 @@ var DATE_FORMAT_TYPES, NUMBER_FORMAT_TYPES, valueFormatter, quillFormat, quillAu
73
156
  var init_valueFormatter = __esm({
74
157
  "src/utils/valueFormatter.ts"() {
75
158
  "use strict";
159
+ init_textProcessing();
76
160
  DATE_FORMAT_TYPES = [
77
161
  "yyyy",
78
162
  "MMM_yyyy",
@@ -235,7 +319,7 @@ var init_valueFormatter = __esm({
235
319
  if (typeof value === "object") {
236
320
  return JSON.stringify(value);
237
321
  }
238
- return value.toString();
322
+ return formatIdentifierLabel(value.toString());
239
323
  };
240
324
  formatterDollar = new Intl.NumberFormat("en-US", {
241
325
  style: "currency",
@@ -508,78 +592,6 @@ var init_ast = __esm({
508
592
  }
509
593
  });
510
594
 
511
- // src/utils/textProcessing.ts
512
- function capitalize(text) {
513
- return text.charAt(0).toUpperCase() + text.slice(1);
514
- }
515
- function matchCasing(text, template) {
516
- if (!text || !template) {
517
- return text ?? "";
518
- }
519
- const isTitleCase = (str) => /^[A-Z][a-z]*([A-Z][a-z]*)*$/.test(str);
520
- const isCamelCase = (str) => /^[a-z]+([A-Z][a-z]*)*$/.test(str);
521
- const isSnakeCase = (str) => /^[a-z0-9]+(_[a-z0-9]+)*$/.test(str);
522
- const isAllLowerCase = (str) => /^[a-z]+$/.test(str);
523
- const isAllUpperCase = (str) => /^[A-Z]+$/.test(str);
524
- const isCapitalized = (str) => /^[A-Z][a-z]*$/.test(str);
525
- const isScreamingSnakeCase = (str) => /^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$/.test(str);
526
- const toTitleCase = (str) => str.toLowerCase().replace(/\b\w/g, (char) => char.toUpperCase());
527
- const toCamelCase = (str) => str.replace(/_./g, (match) => match.charAt(1).toUpperCase()).toLowerCase();
528
- const toSnakeCase = (str) => str.replace(/[A-Z]/g, (match) => `_${match.toLowerCase()}`);
529
- const toLowerCase = (str) => str.toLowerCase();
530
- const toUpperCase = (str) => str.toUpperCase();
531
- const toCapitalized = (str) => str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
532
- const toScreamingSnakeCase = (str) => str.replace(/([A-Z])/g, "_$1").replace(/^_/, "").toUpperCase();
533
- if (isTitleCase(template)) {
534
- return toTitleCase(text);
535
- } else if (isCamelCase(template)) {
536
- return toCamelCase(text);
537
- } else if (isSnakeCase(template)) {
538
- return toSnakeCase(text);
539
- } else if (isAllLowerCase(template)) {
540
- return toLowerCase(text);
541
- } else if (isAllUpperCase(template)) {
542
- return toUpperCase(text);
543
- } else if (isCapitalized(template)) {
544
- return toCapitalized(text);
545
- } else if (isScreamingSnakeCase(template)) {
546
- return toScreamingSnakeCase(text);
547
- } else {
548
- return text;
549
- }
550
- }
551
- function snakeCaseToTitleCase(str) {
552
- if (!str) {
553
- return str;
554
- }
555
- return str.toString().split(/_| /).map(
556
- (word) => word === "id" ? "ID" : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
557
- ).join(" ");
558
- }
559
- function snakeAndCamelCaseToTitleCase(str) {
560
- if (!str || typeof str !== "string") {
561
- return str;
562
- }
563
- if (str.includes("_")) {
564
- return str.split(/_| /).map((word) => word === "id" ? "ID" : capitalize(word)).join(" ");
565
- } else {
566
- const text = str.replace(/([a-z])([A-Z])/g, "$1 $2");
567
- const newText = text.split(" ").map((word) => word === "Id" || word === "id" ? "ID" : capitalize(word)).join(" ");
568
- return newText;
569
- }
570
- }
571
- function removeDoubleQuotes(str) {
572
- if (!str) {
573
- return str;
574
- }
575
- return str.replace(/"/g, "");
576
- }
577
- var init_textProcessing = __esm({
578
- "src/utils/textProcessing.ts"() {
579
- "use strict";
580
- }
581
- });
582
-
583
595
  // src/components/ReportBuilder/bigDateMap.ts
584
596
  function cleanDateFieldName(fieldName) {
585
597
  if (!fieldName) return void 0;
@@ -15133,6 +15145,63 @@ function getDateString(value, dateRange, dateBucket, databaseType) {
15133
15145
  function isDateField(fieldType) {
15134
15146
  return fieldType === "date" || fieldType === "datetime" || fieldType === "timestamp" || fieldType === "timestamptz" || fieldType === "yyyy" || fieldType === "MMM_yyyy" || fieldType === "MMM_dd" || fieldType === "MMM_dd_yyyy" || fieldType === "MMM_dd_hh:mm_ap_pm" || fieldType === "hh_ap_pm";
15135
15147
  }
15148
+ function getExclusiveDateBucketRange(startInput, bucket) {
15149
+ const parsed = startInput instanceof Date ? startInput : new Date(startInput);
15150
+ if (Number.isNaN(parsed.getTime())) {
15151
+ throw new Error(`Invalid bucket start date: ${String(startInput)}`);
15152
+ }
15153
+ let start;
15154
+ let endExclusive;
15155
+ switch (bucket) {
15156
+ case "day": {
15157
+ start = new Date(
15158
+ Date.UTC(
15159
+ parsed.getUTCFullYear(),
15160
+ parsed.getUTCMonth(),
15161
+ parsed.getUTCDate()
15162
+ )
15163
+ );
15164
+ endExclusive = new Date(start);
15165
+ endExclusive.setUTCDate(endExclusive.getUTCDate() + 1);
15166
+ break;
15167
+ }
15168
+ case "week": {
15169
+ const day = parsed.getUTCDay();
15170
+ start = new Date(
15171
+ Date.UTC(
15172
+ parsed.getUTCFullYear(),
15173
+ parsed.getUTCMonth(),
15174
+ parsed.getUTCDate() - (day + 6) % 7
15175
+ )
15176
+ );
15177
+ endExclusive = new Date(start);
15178
+ endExclusive.setUTCDate(endExclusive.getUTCDate() + 7);
15179
+ break;
15180
+ }
15181
+ case "month": {
15182
+ start = new Date(
15183
+ Date.UTC(parsed.getUTCFullYear(), parsed.getUTCMonth(), 1)
15184
+ );
15185
+ endExclusive = new Date(
15186
+ Date.UTC(parsed.getUTCFullYear(), parsed.getUTCMonth() + 1, 1)
15187
+ );
15188
+ break;
15189
+ }
15190
+ case "year": {
15191
+ start = new Date(Date.UTC(parsed.getUTCFullYear(), 0, 1));
15192
+ endExclusive = new Date(Date.UTC(parsed.getUTCFullYear() + 1, 0, 1));
15193
+ break;
15194
+ }
15195
+ default: {
15196
+ const _exhaustive = bucket;
15197
+ throw new Error(`Unsupported date bucket: ${String(_exhaustive)}`);
15198
+ }
15199
+ }
15200
+ return {
15201
+ start: start.toISOString(),
15202
+ endExclusive: endExclusive.toISOString()
15203
+ };
15204
+ }
15136
15205
  var init_dates = __esm({
15137
15206
  "src/utils/dates.ts"() {
15138
15207
  "use strict";
@@ -17252,7 +17321,7 @@ async function generatePivotWithSQL({
17252
17321
  client,
17253
17322
  task: "pivot-template",
17254
17323
  metadata: {
17255
- clientId: client.clientId,
17324
+ clientId: client.id,
17256
17325
  pivot: pivotConfig,
17257
17326
  reportId: report?.id !== "__quillTempReport" ? report?.id : void 0,
17258
17327
  itemQuery: reportBuilderState ? void 0 : report?.queryString,
@@ -19077,7 +19146,7 @@ var init_tableProcessing = __esm({
19077
19146
  metadata: {
19078
19147
  reportBuilderState,
19079
19148
  stringColumns: stringColumns.map((col) => col.field),
19080
- clientId: client.clientId,
19149
+ clientId: client.id,
19081
19150
  databaseType: client.databaseType?.toLowerCase() || "postgresql",
19082
19151
  customFields,
19083
19152
  filters: void 0,
@@ -19268,7 +19337,7 @@ var init_tableProcessing = __esm({
19268
19337
  metadata: {
19269
19338
  reportBuilderState,
19270
19339
  columns: stringNames,
19271
- clientId: client.publicKey,
19340
+ clientId: client.id,
19272
19341
  databaseType: client.databaseType,
19273
19342
  customFieldsByTable: customFields,
19274
19343
  useNewNodeSql: true,
@@ -19283,7 +19352,7 @@ var init_tableProcessing = __esm({
19283
19352
  task: "query",
19284
19353
  metadata: {
19285
19354
  query: countQuery,
19286
- clientId: client.publicKey,
19355
+ clientId: client.id,
19287
19356
  databaseType: client.databaseType,
19288
19357
  customFieldsByTable: customFields,
19289
19358
  useNewNodeSql: true,
@@ -19343,7 +19412,7 @@ var init_tableProcessing = __esm({
19343
19412
  metadata: {
19344
19413
  reportBuilderState,
19345
19414
  stringColumns: columns,
19346
- clientId: client.clientId,
19415
+ clientId: client.id,
19347
19416
  databaseType: client.databaseType?.toLowerCase() || "postgresql",
19348
19417
  customFields,
19349
19418
  filters,
@@ -19393,7 +19462,7 @@ var init_tableProcessing = __esm({
19393
19462
  task: "query",
19394
19463
  metadata: {
19395
19464
  query,
19396
- clientId: client.publicKey,
19465
+ clientId: client.id,
19397
19466
  databaseType: client.databaseType,
19398
19467
  customFieldsByTable: customFields,
19399
19468
  useNewNodeSql: true,
@@ -19505,7 +19574,7 @@ var init_tableProcessing = __esm({
19505
19574
  task: "query",
19506
19575
  metadata: {
19507
19576
  query,
19508
- clientId: client.publicKey,
19577
+ clientId: client.id,
19509
19578
  databaseType: client.databaseType,
19510
19579
  customFieldsByTable: customFields,
19511
19580
  useNewNodeSql: true,
@@ -19634,7 +19703,7 @@ var init_tableProcessing = __esm({
19634
19703
  metadata: {
19635
19704
  query,
19636
19705
  filterMap,
19637
- clientId: client.publicKey,
19706
+ clientId: client.id,
19638
19707
  databaseType: client?.databaseType,
19639
19708
  customFieldsByTable: customFields,
19640
19709
  additionalProcessing: processing,
@@ -19669,7 +19738,7 @@ var init_tableProcessing = __esm({
19669
19738
  task: "log-broken-query",
19670
19739
  metadata: {
19671
19740
  query,
19672
- clientId: client.clientId,
19741
+ clientId: client.id,
19673
19742
  error: parsingError
19674
19743
  },
19675
19744
  getToken
@@ -19780,7 +19849,7 @@ var init_tableProcessing = __esm({
19780
19849
  metadata: {
19781
19850
  dashboardItemId: reportId,
19782
19851
  filters: minimalFilters,
19783
- clientId: client?.publicKey,
19852
+ clientId: client?.id,
19784
19853
  databaseType: client?.databaseType,
19785
19854
  additionalProcessing: updatedProcessing,
19786
19855
  forcePagination: true,
@@ -19853,7 +19922,7 @@ var init_tableProcessing = __esm({
19853
19922
  rowCountOnly,
19854
19923
  customFields,
19855
19924
  tenants,
19856
- clientId: client.clientId,
19925
+ clientId: client.id,
19857
19926
  databaseType: client.databaseType?.toLowerCase() || "postgresql",
19858
19927
  dashboardName,
19859
19928
  ...reportId ? {
@@ -19991,27 +20060,6 @@ function parseData(rows, queryType) {
19991
20060
  return rows;
19992
20061
  }
19993
20062
  }
19994
- function isQuillFetchDebugEnabled() {
19995
- if (typeof globalThis !== "undefined") {
19996
- for (const debugFlag of QUILL_FETCH_DEBUG_FLAGS) {
19997
- if (globalThis?.[debugFlag] === true) {
19998
- return true;
19999
- }
20000
- }
20001
- }
20002
- if (typeof process !== "undefined" && typeof process.env !== "undefined") {
20003
- const envCandidates = [
20004
- process?.env?.QUILL_DEBUG_USEFORM_HYDRATION,
20005
- process?.env?.QUILL_DEBUG_USEFORM_FILTERS,
20006
- process?.env?.QUILL_DEBUG_DATA_FETCHER
20007
- ];
20008
- return envCandidates.some((candidate) => {
20009
- const normalized = String(candidate ?? "").trim().toLowerCase();
20010
- return normalized === "1" || normalized === "true";
20011
- });
20012
- }
20013
- return false;
20014
- }
20015
20063
  async function testSqlViewState(client, referencedTables, getToken) {
20016
20064
  let errorMessage = null;
20017
20065
  await Promise.all(
@@ -20024,7 +20072,7 @@ async function testSqlViewState(client, referencedTables, getToken) {
20024
20072
  task: "test-view",
20025
20073
  metadata: {
20026
20074
  tables: [table],
20027
- clientId: client.clientId
20075
+ clientId: client.id
20028
20076
  },
20029
20077
  getToken
20030
20078
  });
@@ -20033,7 +20081,7 @@ async function testSqlViewState(client, referencedTables, getToken) {
20033
20081
  metadata: {
20034
20082
  table,
20035
20083
  task: "set-broken-view",
20036
- clientId: client.clientId
20084
+ clientId: client.id
20037
20085
  }
20038
20086
  };
20039
20087
  quillFetch({
@@ -20143,7 +20191,7 @@ async function* quillStream({
20143
20191
  body: JSON.stringify({
20144
20192
  metadata: {
20145
20193
  task,
20146
- clientId: client.clientId,
20194
+ clientId: client.id,
20147
20195
  ...metadata
20148
20196
  }
20149
20197
  }),
@@ -20372,7 +20420,7 @@ async function getData(client, cloudQueryEndpoint, noCred, hostedRequestBody, cl
20372
20420
  body: method === "POST" ? JSON.stringify({
20373
20421
  ...cloudRequestBody,
20374
20422
  ...{
20375
- publicKey: client?.publicKey
20423
+ publicKey: client?.id
20376
20424
  }
20377
20425
  }) : null,
20378
20426
  signal: abortSignal
@@ -20401,7 +20449,7 @@ async function fetchSqlQuery(ast, client, getToken, formData) {
20401
20449
  client,
20402
20450
  task: "sqlify",
20403
20451
  metadata: {
20404
- clientId: client.clientId,
20452
+ clientId: client.id,
20405
20453
  useNewNodeSql: true,
20406
20454
  ast: { ...ast, where }
20407
20455
  },
@@ -20422,7 +20470,7 @@ async function fetchSqlQueryFromState(reportBuilderState, client, getToken, data
20422
20470
  client,
20423
20471
  task: "sqlify",
20424
20472
  metadata: {
20425
- clientId: client.clientId,
20473
+ clientId: client.id,
20426
20474
  useNewNodeSql: true,
20427
20475
  ast
20428
20476
  },
@@ -20439,7 +20487,7 @@ async function fetchQueryDateRangesFromState(reportBuilderState, columns, client
20439
20487
  client,
20440
20488
  task: "report-builder-date-ranges",
20441
20489
  metadata: {
20442
- clientId: client.clientId,
20490
+ clientId: client.id,
20443
20491
  reportBuilderState,
20444
20492
  dateColumns: columns,
20445
20493
  databaseType: databaseType || "postgresql",
@@ -20497,7 +20545,7 @@ async function fetchRelevantInfoFromState(reportBuilderState, tables, columns, a
20497
20545
  return { error: error.message };
20498
20546
  }
20499
20547
  }
20500
- var QUILL_FETCH_DEBUG_FLAGS, quillFetchDebugSeq, logQuillFetchDebug, quillFetch, parseFetchResponse;
20548
+ var quillFetch, parseFetchResponse;
20501
20549
  var init_dataFetcher = __esm({
20502
20550
  "src/utils/dataFetcher.tsx"() {
20503
20551
  "use strict";
@@ -20506,16 +20554,6 @@ var init_dataFetcher = __esm({
20506
20554
  init_tableProcessing();
20507
20555
  init_dates();
20508
20556
  init_changelogNotify();
20509
- QUILL_FETCH_DEBUG_FLAGS = [
20510
- "__QUILL_DEBUG_USEFORM_HYDRATION__",
20511
- "__QUILL_DEBUG_USEFORM_FILTERS__",
20512
- "__QUILL_DEBUG_DATA_FETCHER__"
20513
- ];
20514
- quillFetchDebugSeq = 0;
20515
- logQuillFetchDebug = (label, payload) => {
20516
- if (!isQuillFetchDebugEnabled()) return;
20517
- console.log(`[quillFetch-debug] ${label}`, payload);
20518
- };
20519
20557
  quillFetch = async ({
20520
20558
  client,
20521
20559
  task,
@@ -20526,24 +20564,7 @@ var init_dataFetcher = __esm({
20526
20564
  urlParameters,
20527
20565
  getToken
20528
20566
  }) => {
20529
- const debugSeq = ++quillFetchDebugSeq;
20530
- const debugStart = Date.now();
20531
- logQuillFetchDebug("request", {
20532
- seq: debugSeq,
20533
- task,
20534
- reportId: metadata?.reportId,
20535
- dashboardItemId: metadata?.dashboardItemId,
20536
- hasPivot: Boolean(metadata?.pivot),
20537
- hasReportBuilderState: Boolean(metadata?.reportBuilderState),
20538
- filtersLength: Array.isArray(metadata?.filters) ? metadata.filters.length : void 0
20539
- });
20540
20567
  const token = await getToken();
20541
- logQuillFetchDebug("token-acquired", {
20542
- seq: debugSeq,
20543
- task,
20544
- ms: Date.now() - debugStart,
20545
- hasToken: Boolean(token)
20546
- });
20547
20568
  const queryString = urlParameters ?? `task=${task}`;
20548
20569
  const endpoint = client.queryEndpoint ? `${client.queryEndpoint}?${queryString}` : `${QUILL_SERVER}${QUILL_QUERY_ENDPOINT}?${queryString}`;
20549
20570
  try {
@@ -20557,7 +20578,7 @@ var init_dataFetcher = __esm({
20557
20578
  body: JSON.stringify({
20558
20579
  metadata: {
20559
20580
  task,
20560
- clientId: client.clientId,
20581
+ clientId: client.id ?? client.clientId,
20561
20582
  ...metadata
20562
20583
  }
20563
20584
  }),
@@ -20575,17 +20596,6 @@ var init_dataFetcher = __esm({
20575
20596
  if (task !== "fetch-changelog-list" && Array.isArray(normalizedData?.changelogs)) {
20576
20597
  notifyChangelogs(normalizedData.changelogs);
20577
20598
  }
20578
- logQuillFetchDebug("response", {
20579
- seq: debugSeq,
20580
- task,
20581
- ms: Date.now() - debugStart,
20582
- status: result.status,
20583
- error: result.error,
20584
- dataError: normalizedData?.error,
20585
- queryResultRowCounts: Array.isArray(result.queries?.queryResults) ? result.queries.queryResults.map(
20586
- (qr) => Array.isArray(qr?.rows) ? qr.rows.length : null
20587
- ) : void 0
20588
- });
20589
20599
  return {
20590
20600
  data: normalizedData,
20591
20601
  queries: result.queries,
@@ -20594,19 +20604,8 @@ var init_dataFetcher = __esm({
20594
20604
  };
20595
20605
  } catch (e) {
20596
20606
  if (e instanceof Error && e.name === "AbortError") {
20597
- logQuillFetchDebug("aborted", {
20598
- seq: debugSeq,
20599
- task,
20600
- ms: Date.now() - debugStart
20601
- });
20602
20607
  throw e;
20603
20608
  }
20604
- logQuillFetchDebug("threw", {
20605
- seq: debugSeq,
20606
- task,
20607
- ms: Date.now() - debugStart,
20608
- message: e instanceof Error ? e.message : String(e)
20609
- });
20610
20609
  if (task !== "set-section-order") {
20611
20610
  console.error("Failed to fetch:", e);
20612
20611
  }
@@ -21528,7 +21527,7 @@ async function getDashboard(dashboardName, client, getToken, tenants, flags) {
21528
21527
  task: "dashboard",
21529
21528
  metadata: {
21530
21529
  name: dashboardName,
21531
- clientId: client.publicKey,
21530
+ clientId: client.id,
21532
21531
  databaseType: client.databaseType,
21533
21532
  useNewNodeSql: true,
21534
21533
  tenants,
@@ -21903,7 +21902,7 @@ function createPivotTemplateMetadata({
21903
21902
  reportId,
21904
21903
  dashboardItemId: reportId,
21905
21904
  ...draftSessionId ? { draftSessionId: String(draftSessionId).trim() } : {},
21906
- clientId: client.publicKey,
21905
+ clientId: client.id,
21907
21906
  databaseType: client.databaseType,
21908
21907
  filters: removeFilterOptions(filters),
21909
21908
  additionalProcessing: normalizedAdditionalProcessing,
@@ -22220,7 +22219,7 @@ async function fetchReportRows({
22220
22219
  task: "report",
22221
22220
  metadata: {
22222
22221
  reportId,
22223
- clientId: client.publicKey,
22222
+ clientId: client.id,
22224
22223
  databaseType: client.databaseType,
22225
22224
  filters: filters.map((filter) => ({ ...filter, options: void 0 })),
22226
22225
  useNewNodeSql: true,
@@ -22290,7 +22289,7 @@ async function fetchReport({
22290
22289
  reportId,
22291
22290
  dashboardItemId: reportId,
22292
22291
  ...draftSessionId ? { draftSessionId: String(draftSessionId).trim() } : {},
22293
- clientId: client.publicKey,
22292
+ clientId: client.id,
22294
22293
  databaseType: client.databaseType,
22295
22294
  filters: filters.map((filter) => ({ ...filter, options: void 0 })),
22296
22295
  customFields,
@@ -22427,7 +22426,7 @@ async function fetchReportName({
22427
22426
  task: "report-name",
22428
22427
  metadata: {
22429
22428
  reportId,
22430
- clientId: client.publicKey,
22429
+ clientId: client.id,
22431
22430
  databaseType: client.databaseType,
22432
22431
  tenants
22433
22432
  },
@@ -22451,7 +22450,7 @@ async function fetchReportRowCount(reportId, client, getToken, tenants, flags, u
22451
22450
  metadata: {
22452
22451
  reportId,
22453
22452
  dashboardItemId: reportId,
22454
- clientId: client.publicKey,
22453
+ clientId: client.id,
22455
22454
  databaseType: client.databaseType,
22456
22455
  filters: filters.map((filter) => ({ ...filter, options: void 0 })),
22457
22456
  customFields,
@@ -22481,7 +22480,7 @@ async function saveReport({
22481
22480
  tenants,
22482
22481
  draftSessionId
22483
22482
  }) {
22484
- const { publicKey, databaseType } = client;
22483
+ const { id, databaseType } = client;
22485
22484
  const {
22486
22485
  reportBuilderState,
22487
22486
  queryString,
@@ -22521,7 +22520,7 @@ async function saveReport({
22521
22520
  ...dashboardItemId ? { reportId: dashboardItemId } : {},
22522
22521
  ...draftSessionId ? { draftSessionId: String(draftSessionId).trim() } : {},
22523
22522
  // Remove useNewNodeSql since backend will handle conversion
22524
- clientId: publicKey,
22523
+ clientId: id,
22525
22524
  tenants,
22526
22525
  // Only include adminMode for 'create' task, not 'create-report'
22527
22526
  ...isCreateTask && { adminMode },
@@ -23335,7 +23334,6 @@ var getSchemaInfo = async ({
23335
23334
  getToken,
23336
23335
  eventTracking
23337
23336
  }) => {
23338
- const { publicKey } = client;
23339
23337
  let customFieldsByTableUnique = null;
23340
23338
  if (client.featureFlags?.customFieldsEnabled && tenants && tenants[0] !== "QUILL_ALL_TENANTS" && tenants.length === 1 && (typeof tenants[0] !== "object" || tenants[0].tenantIds?.[0] !== "QUILL_ALL_TENANTS" && tenants[0].tenantIds?.length === 1)) {
23341
23339
  try {
@@ -23354,13 +23352,13 @@ var getSchemaInfo = async ({
23354
23352
  client,
23355
23353
  task: "schema",
23356
23354
  metadata: {
23357
- clientId: publicKey,
23355
+ clientId: client.id,
23358
23356
  removeCustomerField: true,
23359
23357
  removeCustomFieldRef: true,
23360
23358
  tableIds,
23361
23359
  customFieldsByTable: customFieldsByTableUnique,
23362
23360
  useNewCustomFields: true,
23363
- gatherSchemaData: "665610862cf7a3000be66453" === publicKey ? true : false,
23361
+ gatherSchemaData: "665610862cf7a3000be66453" === client.id ? true : false,
23364
23362
  // TODO: this should be a feature flag on the client
23365
23363
  tenants
23366
23364
  },
@@ -24477,7 +24475,7 @@ var CacheCab = class {
24477
24475
  task: "report",
24478
24476
  metadata: {
24479
24477
  reportId,
24480
- clientId: client.publicKey,
24478
+ clientId: client.id,
24481
24479
  databaseType: client.databaseType,
24482
24480
  filters: adjusted,
24483
24481
  additionalProcessing: { page: { rowsPerPage: 1e3, rowsPerRequest: 1e5 } },
@@ -24616,7 +24614,7 @@ var CacheCab = class {
24616
24614
  );
24617
24615
  const keyParts = [
24618
24616
  reportId,
24619
- client.publicKey,
24617
+ client.id,
24620
24618
  client.databaseType,
24621
24619
  hashString(stableStringify(canonicalizeForKey(tenants ?? null))),
24622
24620
  hashString(stableStringify(canonicalizeForKey(flags ?? null))),
@@ -25254,12 +25252,11 @@ var ContextProvider = ({
25254
25252
  typeof window !== "undefined" && sessionStorage ? JSON.parse(sessionStorage.getItem("quill-client") ?? "null") : null
25255
25253
  );
25256
25254
  const populatedClient = useMemo(() => {
25257
- if (!client || client.clientId !== publicKey) return null;
25255
+ if (!client || client.id !== publicKey) return null;
25258
25256
  return {
25259
25257
  ...client,
25260
- publicKey,
25261
- _id: publicKey,
25262
25258
  id: publicKey,
25259
+ clientId: publicKey,
25263
25260
  queryHeaders,
25264
25261
  queryEndpoint,
25265
25262
  streamEndpoint,
@@ -25422,7 +25419,7 @@ var ContextProvider = ({
25422
25419
  try {
25423
25420
  const result = await quillFetch({
25424
25421
  client: {
25425
- clientId: publicKey,
25422
+ id: publicKey,
25426
25423
  queryEndpoint,
25427
25424
  queryHeaders,
25428
25425
  withCredentials: !!withCredentials
@@ -25544,7 +25541,7 @@ var ContextProvider = ({
25544
25541
  try {
25545
25542
  const resp = await quillFetch({
25546
25543
  client: {
25547
- clientId: publicKey,
25544
+ id: publicKey,
25548
25545
  queryEndpoint,
25549
25546
  queryHeaders,
25550
25547
  withCredentials: !!withCredentials
@@ -25552,7 +25549,7 @@ var ContextProvider = ({
25552
25549
  task: fetchRows ? "report" : "report-info",
25553
25550
  metadata: {
25554
25551
  reportId,
25555
- clientId: populatedClient.publicKey,
25552
+ clientId: populatedClient.id,
25556
25553
  useNewNodeSql: true,
25557
25554
  filters: filters?.map((f) => ({ ...f, options: void 0 })),
25558
25555
  additionalProcessing,
@@ -25735,7 +25732,7 @@ var ContextProvider = ({
25735
25732
  try {
25736
25733
  const result = await quillFetch({
25737
25734
  client: {
25738
- clientId: publicKey,
25735
+ id: publicKey,
25739
25736
  queryEndpoint,
25740
25737
  queryHeaders,
25741
25738
  withCredentials: !!withCredentials
@@ -25955,7 +25952,7 @@ var ContextProvider = ({
25955
25952
  });
25956
25953
  return curDashboardConfig;
25957
25954
  }
25958
- if (!populatedClient || !populatedClient.publicKey) {
25955
+ if (!populatedClient || !populatedClient.id) {
25959
25956
  return curDashboardConfig;
25960
25957
  }
25961
25958
  if (dashboardName === null || dashboardName === void 0)
@@ -26109,7 +26106,7 @@ var ContextProvider = ({
26109
26106
  try {
26110
26107
  const result = await quillFetch({
26111
26108
  client: {
26112
- clientId: publicKey2,
26109
+ id: publicKey2,
26113
26110
  queryEndpoint,
26114
26111
  queryHeaders,
26115
26112
  withCredentials: !!withCredentials
@@ -26652,8 +26649,7 @@ var ContextProvider = ({
26652
26649
  withCredentials: withCredentials ?? false,
26653
26650
  databaseType: envClient.databaseType,
26654
26651
  name: envClient.name,
26655
- clientId: publicKey2,
26656
- publicKey: publicKey2,
26652
+ id: publicKey2,
26657
26653
  featureFlags: envClient.featureFlags,
26658
26654
  clerkOrgId: envClient.clerkOrgId,
26659
26655
  allTenantTypes: hydratedTenantTypes
@@ -26725,16 +26721,16 @@ var ContextProvider = ({
26725
26721
  }, [publicKey]);
26726
26722
  useEffect(() => {
26727
26723
  if (!hasHandledInitialPopulatedClient.current) {
26728
- if (!populatedClient?.publicKey && !populatedClient?.currentTenants) {
26724
+ if (!populatedClient?.id && !populatedClient?.currentTenants) {
26729
26725
  return;
26730
26726
  }
26731
26727
  hasHandledInitialPopulatedClient.current = true;
26732
- currentPublicKey.current = populatedClient?.publicKey ?? null;
26728
+ currentPublicKey.current = populatedClient?.id ?? null;
26733
26729
  currentTenant.current = populatedClient?.currentTenants ?? null;
26734
26730
  return;
26735
26731
  }
26736
26732
  let publicKeyChanged = false;
26737
- if (populatedClient?.publicKey && currentPublicKey.current !== populatedClient?.publicKey) {
26733
+ if (populatedClient?.id && currentPublicKey.current !== populatedClient?.id) {
26738
26734
  publicKeyChanged = true;
26739
26735
  dispatch({ type: "CLEAR_DASHBOARDS" });
26740
26736
  dashboardFiltersDispatch({ type: "CLEAR_DASHBOARD_FILTERS" });
@@ -26743,7 +26739,7 @@ var ContextProvider = ({
26743
26739
  backfilledDashboards.current.clear();
26744
26740
  if (isAdmin) {
26745
26741
  setIsDashboardsLoading(true);
26746
- fetchDashboards(populatedClient?.publicKey);
26742
+ fetchDashboards(populatedClient?.id);
26747
26743
  } else {
26748
26744
  setIsDashboardsLoading(false);
26749
26745
  }
@@ -26775,17 +26771,17 @@ var ContextProvider = ({
26775
26771
  })
26776
26772
  );
26777
26773
  }
26778
- if (populatedClient?.currentTenants && populatedClient?.publicKey) {
26774
+ if (populatedClient?.currentTenants && populatedClient?.id) {
26779
26775
  const tenant = typeof populatedClient?.currentTenants[0] === "object" ? populatedClient?.currentTenants[0]?.tenantField : void 0;
26780
26776
  const tenantIds = tenant && typeof populatedClient?.currentTenants[0] === "object" ? populatedClient?.currentTenants[0]?.tenantIds : populatedClient?.currentTenants;
26781
26777
  eventTracking?.setUser?.({
26782
- clientId: populatedClient.publicKey,
26778
+ clientId: populatedClient.id,
26783
26779
  clerkOrgId: populatedClient.clerkOrgId,
26784
26780
  tenant,
26785
26781
  tenantIds
26786
26782
  });
26787
26783
  }
26788
- }, [populatedClient?.currentTenants, populatedClient?.publicKey]);
26784
+ }, [populatedClient?.currentTenants, populatedClient?.id]);
26789
26785
  if (!theme) {
26790
26786
  return null;
26791
26787
  }
@@ -27100,7 +27096,7 @@ var useDashboardInternal = (dashboardName, customFilters) => {
27100
27096
  });
27101
27097
  const body = {
27102
27098
  task: "set-section-order",
27103
- clientId: client.clientId,
27099
+ clientId: client.id,
27104
27100
  dashboardName,
27105
27101
  sectionOrder
27106
27102
  };
@@ -27328,7 +27324,7 @@ var useDashboards = () => {
27328
27324
  dateFilter,
27329
27325
  name: name2.trim(),
27330
27326
  task: "edit-dashboard",
27331
- clientId: clientId ?? client.clientId,
27327
+ clientId: clientId ?? client.id,
27332
27328
  tenantKeys: dashboardOwners
27333
27329
  };
27334
27330
  try {
@@ -27403,7 +27399,7 @@ var useDashboards = () => {
27403
27399
  initialCacheDateRange,
27404
27400
  name: name2.trim(),
27405
27401
  task: "edit-dashboard",
27406
- clientId: clientId ?? client.clientId,
27402
+ clientId: clientId ?? client.id,
27407
27403
  tenantKeys
27408
27404
  };
27409
27405
  try {
@@ -27581,7 +27577,7 @@ var useDashboards = () => {
27581
27577
  client,
27582
27578
  task: "delete-dashboard",
27583
27579
  metadata: {
27584
- clientId: client.clientId,
27580
+ clientId: client.id,
27585
27581
  databaseType: client.databaseType,
27586
27582
  name: name2
27587
27583
  }
@@ -28426,7 +28422,7 @@ async function getExportData(client, dashboardFilters, reportId, getToken, event
28426
28422
  metadata: {
28427
28423
  reportId,
28428
28424
  dashboardItemId: reportId,
28429
- clientId: client.publicKey,
28425
+ clientId: client.id,
28430
28426
  databaseType: client?.databaseType,
28431
28427
  filters: minimalFilters,
28432
28428
  useNewNodeSql: true,
@@ -29199,6 +29195,13 @@ function linspace(start, end, num) {
29199
29195
  }
29200
29196
  return result;
29201
29197
  }
29198
+ function stableColorIndex(field) {
29199
+ let hash = 0;
29200
+ for (const character of field.replace("comparison_", "")) {
29201
+ hash = Math.imul(hash, 31) + character.charCodeAt(0) >>> 0;
29202
+ }
29203
+ return hash;
29204
+ }
29202
29205
  function selectColor(element, colors, index) {
29203
29206
  if (!element?.field) return "gray";
29204
29207
  const isComparison = element.field.includes("comparison_");
@@ -31494,15 +31497,19 @@ var QuillPortal = ({
31494
31497
  };
31495
31498
 
31496
31499
  // src/components/Chart/CustomLegend.tsx
31500
+ init_textProcessing();
31497
31501
  import { jsx as jsx27, jsxs as jsxs19 } from "react/jsx-runtime";
31498
31502
  var getLegendLabel = (entry) => {
31499
31503
  const label = entry?.payload?.name ?? entry?.value ?? entry?.dataKey ?? "";
31500
- return typeof label === "string" ? label : String(label ?? "");
31504
+ return snakeAndCamelCaseToTitleCase(
31505
+ typeof label === "string" ? label : String(label ?? "")
31506
+ );
31501
31507
  };
31502
31508
  var LegendItem = ({
31503
31509
  entry,
31504
31510
  index,
31505
- theme
31511
+ theme,
31512
+ onClick
31506
31513
  }) => /* @__PURE__ */ jsx27(
31507
31514
  "div",
31508
31515
  {
@@ -31511,30 +31518,37 @@ var LegendItem = ({
31511
31518
  alignItems: "baseline",
31512
31519
  marginRight: "1rem"
31513
31520
  },
31514
- children: /* @__PURE__ */ jsxs19("div", { style: { display: "flex", flexDirection: "row", alignItems: "center" }, children: [
31515
- /* @__PURE__ */ jsx27(
31516
- "svg",
31517
- {
31518
- style: { marginRight: "0.5rem" },
31519
- width: "16",
31520
- height: "16",
31521
- viewBox: "0 0 16 16",
31522
- children: /* @__PURE__ */ jsx27("rect", { width: "16", height: "16", rx: "3", fill: entry?.color })
31523
- }
31524
- ),
31525
- /* @__PURE__ */ jsx27(
31526
- "span",
31527
- {
31528
- style: {
31529
- color: theme?.secondaryTextColor,
31530
- fontFamily: theme?.fontFamily,
31531
- fontSize: theme?.fontSizeMedium || "14px",
31532
- whiteSpace: "nowrap"
31533
- },
31534
- children: getLegendLabel(entry)
31535
- }
31536
- )
31537
- ] })
31521
+ onClick: () => onClick ? onClick(entry) : void 0,
31522
+ children: /* @__PURE__ */ jsxs19(
31523
+ "div",
31524
+ {
31525
+ style: { display: "flex", flexDirection: "row", alignItems: "center" },
31526
+ children: [
31527
+ /* @__PURE__ */ jsx27(
31528
+ "svg",
31529
+ {
31530
+ style: { marginRight: "0.5rem" },
31531
+ width: "16",
31532
+ height: "16",
31533
+ viewBox: "0 0 16 16",
31534
+ children: /* @__PURE__ */ jsx27("rect", { width: "16", height: "16", rx: "3", fill: entry?.color })
31535
+ }
31536
+ ),
31537
+ /* @__PURE__ */ jsx27(
31538
+ "span",
31539
+ {
31540
+ style: {
31541
+ color: theme?.secondaryTextColor,
31542
+ fontFamily: theme?.fontFamily,
31543
+ fontSize: theme?.fontSizeMedium || "14px",
31544
+ whiteSpace: "nowrap"
31545
+ },
31546
+ children: getLegendLabel(entry)
31547
+ }
31548
+ )
31549
+ ]
31550
+ }
31551
+ )
31538
31552
  },
31539
31553
  `legend-${index}`
31540
31554
  );
@@ -31548,7 +31562,8 @@ var getOuterWidth = (element) => {
31548
31562
  };
31549
31563
  var RenderLegend = ({
31550
31564
  payload,
31551
- limit
31565
+ limit,
31566
+ onClickLegendElement
31552
31567
  }) => {
31553
31568
  const [theme] = useContext5(ThemeContext);
31554
31569
  const [isOpen, setIsOpen] = useState9(false);
@@ -31561,7 +31576,10 @@ var RenderLegend = ({
31561
31576
  const safePayload = payload ?? [];
31562
31577
  const maxItems = limit ?? safePayload.length;
31563
31578
  const measuredLimit = visibleCount ?? maxItems;
31564
- const visiblePayload = safePayload.slice(0, Math.min(maxItems, measuredLimit));
31579
+ const visiblePayload = safePayload.slice(
31580
+ 0,
31581
+ Math.min(maxItems, measuredLimit)
31582
+ );
31565
31583
  const handleOpen = () => setIsOpen(true);
31566
31584
  const handleClose = () => setIsOpen(false);
31567
31585
  useLayoutEffect2(() => {
@@ -31622,7 +31640,6 @@ var RenderLegend = ({
31622
31640
  visibility: "hidden",
31623
31641
  height: 0,
31624
31642
  overflow: "hidden",
31625
- pointerEvents: "none",
31626
31643
  display: "flex",
31627
31644
  alignItems: "center",
31628
31645
  flexWrap: "nowrap",
@@ -31646,7 +31663,15 @@ var RenderLegend = ({
31646
31663
  ref: (element) => {
31647
31664
  itemRefs.current[index] = element;
31648
31665
  },
31649
- children: /* @__PURE__ */ jsx27(LegendItem, { entry, index, theme })
31666
+ children: /* @__PURE__ */ jsx27(
31667
+ LegendItem,
31668
+ {
31669
+ entry,
31670
+ index,
31671
+ theme,
31672
+ onClick: onClickLegendElement
31673
+ }
31674
+ )
31650
31675
  },
31651
31676
  `legend-measure-${index}`
31652
31677
  ))
@@ -31687,7 +31712,8 @@ var RenderLegend = ({
31687
31712
  {
31688
31713
  entry,
31689
31714
  index,
31690
- theme
31715
+ theme,
31716
+ onClick: onClickLegendElement
31691
31717
  },
31692
31718
  `legend-${index}`
31693
31719
  ))
@@ -31734,7 +31760,8 @@ var RenderLegend = ({
31734
31760
  {
31735
31761
  entry,
31736
31762
  index,
31737
- theme
31763
+ theme,
31764
+ onClick: onClickLegendElement
31738
31765
  },
31739
31766
  `legend-popover-${index}`
31740
31767
  ))
@@ -32006,6 +32033,7 @@ var PieChartWrapper = React4.forwardRef(
32006
32033
  containerStyle,
32007
32034
  theme,
32008
32035
  onClickChartElement,
32036
+ onClickLegendElement,
32009
32037
  yAxisFields,
32010
32038
  showLegend = false,
32011
32039
  ...other
@@ -32102,7 +32130,13 @@ var PieChartWrapper = React4.forwardRef(
32102
32130
  paddingBottom: 20,
32103
32131
  fontFamily: theme?.fontFamily
32104
32132
  },
32105
- content: /* @__PURE__ */ jsx28(RenderLegend, { limit: 5 })
32133
+ content: /* @__PURE__ */ jsx28(
32134
+ RenderLegend,
32135
+ {
32136
+ limit: 5,
32137
+ onClickLegendElement
32138
+ }
32139
+ )
32106
32140
  }
32107
32141
  ),
32108
32142
  /* @__PURE__ */ jsx28(
@@ -32745,6 +32779,7 @@ import {
32745
32779
  } from "recharts";
32746
32780
 
32747
32781
  // src/utils/axisFormatter.ts
32782
+ init_textProcessing();
32748
32783
  import { endOfWeek as endOfWeek2, format as format5, getWeek as getWeek2, isValid as isValid5, startOfWeek as startOfWeek5 } from "date-fns";
32749
32784
  import { utcToZonedTime as utcToZonedTime4 } from "date-fns-tz";
32750
32785
  var axisFormatter = ({ value, field, fields }) => {
@@ -32796,7 +32831,7 @@ var formatString2 = (value) => {
32796
32831
  if (typeof value === "object") {
32797
32832
  return JSON.stringify(value);
32798
32833
  }
32799
- return value.toString();
32834
+ return formatIdentifierLabel(value.toString());
32800
32835
  };
32801
32836
  var formatterDecimal2 = new Intl.NumberFormat("en-US", {
32802
32837
  style: "decimal",
@@ -33003,6 +33038,7 @@ function ChartTooltipRow2({
33003
33038
  }
33004
33039
 
33005
33040
  // src/components/Chart/ChartTooltipGroup.tsx
33041
+ init_textProcessing();
33006
33042
  import { jsx as jsx32, jsxs as jsxs23 } from "react/jsx-runtime";
33007
33043
  function ChartTooltipGroup({
33008
33044
  name: name2,
@@ -33037,7 +33073,7 @@ function ChartTooltipGroup({
33037
33073
  paddingBottom: 2,
33038
33074
  textTransform: "capitalize"
33039
33075
  },
33040
- children: name2.replaceAll("_", " ").toLowerCase()
33076
+ children: formatIdentifierLabel(name2)
33041
33077
  }
33042
33078
  ),
33043
33079
  items.map(({ color, value, name: name3 }, idx) => /* @__PURE__ */ jsx32(
@@ -33058,6 +33094,7 @@ function ChartTooltipGroup({
33058
33094
 
33059
33095
  // src/components/Chart/ChartTooltip.tsx
33060
33096
  init_dates();
33097
+ init_textProcessing();
33061
33098
  import { jsx as jsx33, jsxs as jsxs24 } from "react/jsx-runtime";
33062
33099
  var ChartTooltipPrimary = (props) => /* @__PURE__ */ jsxs24(ChartTooltipFrame2, { theme: props.theme, children: [
33063
33100
  /* @__PURE__ */ jsx33(
@@ -33092,7 +33129,7 @@ var ChartTooltipPrimary = (props) => /* @__PURE__ */ jsxs24(ChartTooltipFrame2,
33092
33129
  paddingTop: 2,
33093
33130
  paddingBottom: 2
33094
33131
  },
33095
- children: !isNaN(new Date(props.label)) && props.dateFormatter ? props.dateFormatter(props.label) : !isNaN(new Date(props.label)) ? format6(new Date(props.label), "MMM yyyy") : props.label
33132
+ children: !isNaN(new Date(props.label)) && props.dateFormatter ? props.dateFormatter(props.label) : !isNaN(new Date(props.label)) ? format6(new Date(props.label), "MMM yyyy") : formatIdentifierLabel(props.label)
33096
33133
  }
33097
33134
  )
33098
33135
  }
@@ -33175,7 +33212,7 @@ function reformatComparisonPayload(props, primaryLabel, comparisonLabel) {
33175
33212
  return columnsByKey;
33176
33213
  }
33177
33214
  function getTooltipLabel(props, altTooltipLabel, isDateXAxis) {
33178
- return props.payload.length <= 2 && altTooltipLabel && isDateXAxis ? !isNaN(new Date(altTooltipLabel)) && props.dateFormatter ? props.dateFormatter(altTooltipLabel) : !isNaN(new Date(altTooltipLabel)) ? format6(new Date(altTooltipLabel), "MMM yyyy") : altTooltipLabel : !isNaN(new Date(props.label)) && props.dateFormatter ? props.dateFormatter(props.label) : !isNaN(new Date(props.label)) ? format6(new Date(props.label), "MMM yyyy") : props.label;
33215
+ return props.payload.length <= 2 && altTooltipLabel && isDateXAxis ? !isNaN(new Date(altTooltipLabel)) && props.dateFormatter ? props.dateFormatter(altTooltipLabel) : !isNaN(new Date(altTooltipLabel)) ? format6(new Date(altTooltipLabel), "MMM yyyy") : formatIdentifierLabel(altTooltipLabel) : !isNaN(new Date(props.label)) && props.dateFormatter ? props.dateFormatter(props.label) : !isNaN(new Date(props.label)) ? format6(new Date(props.label), "MMM yyyy") : formatIdentifierLabel(props.label);
33179
33216
  }
33180
33217
  function ChartTooltipComparison(props) {
33181
33218
  const isDateXAxis = isDateFormat2(props.xAxisFormat);
@@ -33431,6 +33468,7 @@ function CustomReferenceLine({
33431
33468
 
33432
33469
  // src/components/Chart/LineChart.tsx
33433
33470
  init_columnProcessing();
33471
+ init_textProcessing();
33434
33472
  import { jsx as jsx35, jsxs as jsxs26 } from "react/jsx-runtime";
33435
33473
  function createLineForEmptyChart(yAxisFields, dateFilter, xAxisField, xAxisFormat) {
33436
33474
  let lineChartData = [];
@@ -33467,6 +33505,8 @@ function LineChart({
33467
33505
  cartesianGridLineColor,
33468
33506
  onClickChartElement = () => {
33469
33507
  },
33508
+ onClickLegendElement = () => {
33509
+ },
33470
33510
  dateFilter,
33471
33511
  referenceLines,
33472
33512
  showLegend = false
@@ -33563,7 +33603,7 @@ function LineChart({
33563
33603
  paddingBottom: 20,
33564
33604
  fontFamily: theme?.fontFamily
33565
33605
  },
33566
- content: /* @__PURE__ */ jsx35(RenderLegend, {})
33606
+ content: /* @__PURE__ */ jsx35(RenderLegend, { onClickLegendElement })
33567
33607
  }
33568
33608
  ),
33569
33609
  /* @__PURE__ */ jsx35(
@@ -33651,7 +33691,9 @@ function LineChart({
33651
33691
  color: p.color || "black",
33652
33692
  chartType: "line",
33653
33693
  dataKey: p.dataKey?.toLocaleString() || "",
33654
- name: name2 || p.name?.toString() || "",
33694
+ name: snakeAndCamelCaseToTitleCase(
33695
+ name2 || p.name?.toString() || ""
33696
+ ),
33655
33697
  payload: p.payload || {},
33656
33698
  type: p.type || "none",
33657
33699
  unit: "string",
@@ -33744,6 +33786,7 @@ function LineChart({
33744
33786
  Area,
33745
33787
  {
33746
33788
  type: "linear",
33789
+ name: elem.label || elem.field,
33747
33790
  dataKey: elem.field,
33748
33791
  stroke: getCustomColor(index, elem.field) ?? selectColor(elem, colors, index - numComparisons),
33749
33792
  fill: `url(#${uniqueId})`,
@@ -33774,6 +33817,7 @@ import {
33774
33817
  Tooltip as Tooltip3
33775
33818
  } from "recharts";
33776
33819
  import { useMemo as useMemo6 } from "react";
33820
+ init_textProcessing();
33777
33821
  import { jsx as jsx36, jsxs as jsxs27 } from "react/jsx-runtime";
33778
33822
  function RadarChart({
33779
33823
  colors,
@@ -33789,6 +33833,8 @@ function RadarChart({
33789
33833
  isAnimationActive = true,
33790
33834
  onClickChartElement = () => {
33791
33835
  },
33836
+ onClickLegendElement = () => {
33837
+ },
33792
33838
  dateFilter,
33793
33839
  showLegend = false
33794
33840
  }) {
@@ -33882,7 +33928,7 @@ function RadarChart({
33882
33928
  paddingBottom: 20,
33883
33929
  fontFamily: theme?.fontFamily
33884
33930
  },
33885
- content: /* @__PURE__ */ jsx36(RenderLegend, {})
33931
+ content: /* @__PURE__ */ jsx36(RenderLegend, { onClickLegendElement })
33886
33932
  }
33887
33933
  ),
33888
33934
  /* @__PURE__ */ jsx36(
@@ -33917,7 +33963,9 @@ function RadarChart({
33917
33963
  color: p.color || "black",
33918
33964
  chartType: "radar",
33919
33965
  dataKey: p.dataKey?.toLocaleString() || "",
33920
- name: name2 || p.name?.toString() || "",
33966
+ name: snakeAndCamelCaseToTitleCase(
33967
+ name2 || p.name?.toString() || ""
33968
+ ),
33921
33969
  payload: p.payload || {},
33922
33970
  type: p.type || "none",
33923
33971
  unit: "string",
@@ -34034,6 +34082,10 @@ var CustomBar = memo((props) => {
34034
34082
  width: rawWidth,
34035
34083
  height: rawHeight,
34036
34084
  fill,
34085
+ fillOpacity,
34086
+ stroke,
34087
+ strokeWidth,
34088
+ style,
34037
34089
  yAxisFields = [],
34038
34090
  dataKey,
34039
34091
  payload = {},
@@ -34091,18 +34143,43 @@ var CustomBar = memo((props) => {
34091
34143
  rawY,
34092
34144
  radius
34093
34145
  ]);
34094
- return /* @__PURE__ */ jsx37("path", { d: path, fill });
34146
+ return /* @__PURE__ */ jsx37(
34147
+ "path",
34148
+ {
34149
+ d: path,
34150
+ fill,
34151
+ fillOpacity,
34152
+ stroke,
34153
+ strokeWidth,
34154
+ style
34155
+ }
34156
+ );
34095
34157
  });
34096
34158
  CustomBar.displayName = "CustomBar";
34097
34159
  var CustomBar_default = CustomBar;
34098
34160
 
34099
34161
  // src/components/Chart/BarChart.tsx
34100
34162
  init_columnProcessing();
34163
+ init_textProcessing();
34101
34164
  import { useMemo as useMemo8 } from "react";
34102
34165
  import { Fragment as Fragment3, jsx as jsx38, jsxs as jsxs28 } from "react/jsx-runtime";
34103
34166
  var CATEGORY_AXIS_WIDTH = 120;
34104
34167
  var VALUE_AXIS_WIDTH = 44;
34105
34168
  var STACKED_DOMAIN_HEADROOM = 1.05;
34169
+ function rowValueFromPivotRow(row, xAxisField, fallbackLabel) {
34170
+ const rawDate = row?.__quillRawDate;
34171
+ if (rawDate != null && rawDate !== "") {
34172
+ return String(rawDate);
34173
+ }
34174
+ const category = row?.[xAxisField];
34175
+ if (category != null && category !== "") {
34176
+ return String(category);
34177
+ }
34178
+ if (fallbackLabel != null && fallbackLabel !== "") {
34179
+ return String(fallbackLabel);
34180
+ }
34181
+ return null;
34182
+ }
34106
34183
  function getStackedDomain(data, fields, comparison) {
34107
34184
  const fieldsArray = fields.filter((field) => comparison || !field.field.startsWith("comparison_")).map((field) => field.field);
34108
34185
  if (fieldsArray.length === 0 || data.length === 0) {
@@ -34124,14 +34201,16 @@ function getStackedDomain(data, fields, comparison) {
34124
34201
  }
34125
34202
  return [0, maxStack * STACKED_DOMAIN_HEADROOM];
34126
34203
  }
34127
- var createCustomBar = (yAxisFields, theme, layout) => {
34204
+ var createCustomBar = (yAxisFields, theme, layout, active = false) => {
34128
34205
  return (props) => /* @__PURE__ */ jsx38(
34129
34206
  CustomBar_default,
34130
34207
  {
34131
34208
  ...props,
34132
34209
  yAxisFields,
34133
34210
  theme,
34134
- layout
34211
+ layout,
34212
+ stroke: active ? theme?.primaryTextColor ?? "#111827" : props.stroke,
34213
+ strokeWidth: active ? 1.5 : props.strokeWidth
34135
34214
  }
34136
34215
  );
34137
34216
  };
@@ -34152,6 +34231,7 @@ function BarChart({
34152
34231
  hideYAxis = false,
34153
34232
  hideCartesianGrid = false,
34154
34233
  onClickChartElement,
34234
+ onClickLegendElement,
34155
34235
  dateFilter,
34156
34236
  referenceLines,
34157
34237
  showLegend = false,
@@ -34204,6 +34284,16 @@ function BarChart({
34204
34284
  return void 0;
34205
34285
  return createCustomBar(sortYAxisFields([...yAxisFields]), theme, layout);
34206
34286
  }, [isStacked, yAxisFields, theme, layout]);
34287
+ const customActiveBarShape = useMemo8(() => {
34288
+ if (!theme?.barChartCornerRadius && !theme?.barChartCornerRadiusRatio)
34289
+ return void 0;
34290
+ return createCustomBar(
34291
+ sortYAxisFields([...yAxisFields]),
34292
+ theme,
34293
+ layout,
34294
+ true
34295
+ );
34296
+ }, [isStacked, yAxisFields, theme, layout]);
34207
34297
  if (!data || data.length === 0) {
34208
34298
  return /* @__PURE__ */ jsx38(
34209
34299
  "div",
@@ -34245,9 +34335,28 @@ function BarChart({
34245
34335
  {
34246
34336
  data: data ?? [],
34247
34337
  layout,
34248
- onClick: (event) => onClickChartElement ? onClickChartElement(
34249
- event?.activePayload ? event.activePayload[0].payload : void 0
34250
- ) : void 0,
34338
+ onClick: (event) => {
34339
+ if (!onClickChartElement || event?.activeLabel === void 0 || event?.activeTooltipIndex === void 0) {
34340
+ return;
34341
+ }
34342
+ const index = Number(event.activeTooltipIndex);
34343
+ const row = event.activePayload?.[0]?.payload ?? data[index] ?? {};
34344
+ onClickChartElement({
34345
+ ...row,
34346
+ interactionType: "bucket",
34347
+ activeLabel: event.activeLabel,
34348
+ rowValue: rowValueFromPivotRow(row, xAxisField, event.activeLabel),
34349
+ columnValue: void 0,
34350
+ activeDataKey: void 0,
34351
+ activeValue: void 0,
34352
+ activePayload: event.activePayload ?? [],
34353
+ category: event.activeLabel,
34354
+ series: void 0,
34355
+ value: void 0,
34356
+ row,
34357
+ index
34358
+ });
34359
+ },
34251
34360
  children: [
34252
34361
  !hideCartesianGrid && /* @__PURE__ */ jsx38(
34253
34362
  CartesianGrid2,
@@ -34267,7 +34376,7 @@ function BarChart({
34267
34376
  wrapperStyle: {
34268
34377
  paddingBottom: 20
34269
34378
  },
34270
- content: /* @__PURE__ */ jsx38(RenderLegend, {})
34379
+ content: /* @__PURE__ */ jsx38(RenderLegend, { onClickLegendElement })
34271
34380
  }
34272
34381
  ),
34273
34382
  isHorizontalBars ? /* @__PURE__ */ jsxs28(Fragment3, { children: [
@@ -34346,11 +34455,13 @@ function BarChart({
34346
34455
  {
34347
34456
  wrapperStyle: { outline: "none", zIndex: 2 },
34348
34457
  isAnimationActive: false,
34349
- cursor: { fill: "#d1d5db", opacity: "0.15" },
34458
+ cursor: false,
34459
+ shared: false,
34350
34460
  content: ({ active, payload, label }) => {
34351
34461
  if (!payload || payload.length === 0) {
34352
34462
  return null;
34353
34463
  }
34464
+ const activeLabel = label ?? payload[0]?.payload?.[xAxisField] ?? "";
34354
34465
  const payloadItems = payload.map((p) => {
34355
34466
  const rawName = yAxisFields?.find(
34356
34467
  (f) => f.field === p.name?.toString()
@@ -34361,7 +34472,9 @@ function BarChart({
34361
34472
  color: p.color || "black",
34362
34473
  chartType: "line",
34363
34474
  dataKey: p.dataKey?.toLocaleString() || "",
34364
- name: name2 || p.name?.toString() || "",
34475
+ name: snakeAndCamelCaseToTitleCase(
34476
+ name2 || p.name?.toString() || ""
34477
+ ),
34365
34478
  payload: p.payload || {},
34366
34479
  type: p.type || "none",
34367
34480
  unit: "string",
@@ -34374,7 +34487,7 @@ function BarChart({
34374
34487
  theme,
34375
34488
  active,
34376
34489
  payload: payloadItems,
34377
- label,
34490
+ label: `${activeLabel}`,
34378
34491
  dateFormatter: (value) => valueFormatter({
34379
34492
  value,
34380
34493
  field: xAxisField,
@@ -34406,21 +34519,47 @@ function BarChart({
34406
34519
  return /* @__PURE__ */ jsx38(
34407
34520
  Bar,
34408
34521
  {
34522
+ name: elem.label || elem.field,
34409
34523
  dataKey: elem.field,
34410
34524
  stackId: stackedMode ? "same_id" : isStacked ? elem.field.replace("comparison_", "") : void 0,
34411
34525
  type: "linear",
34412
- fill: getCustomColor(elem.field) ?? selectColor(
34413
- elem,
34414
- colors.length >= yAxisFields.length / (comparison ? 2 : 1) ? colors : generateArrayFromColor(
34415
- colors.slice(0, 2),
34416
- yAxisFields.length
34417
- ),
34418
- yAxisFields.findIndex(
34419
- (field) => field.field === elem.field?.replace("comparison_", "")
34420
- )
34421
- ),
34526
+ fill: getCustomColor(elem.field) ?? selectColor(elem, colors, stableColorIndex(elem.field)),
34422
34527
  isAnimationActive,
34423
- shape: customBarShape
34528
+ shape: customBarShape,
34529
+ activeBar: customActiveBarShape ?? {
34530
+ fillOpacity: 1,
34531
+ stroke: theme?.primaryTextColor ?? "#111827",
34532
+ strokeWidth: 1.5
34533
+ },
34534
+ style: {
34535
+ cursor: onClickChartElement ? "pointer" : void 0
34536
+ },
34537
+ onClick: (bar, index, event) => {
34538
+ event?.stopPropagation();
34539
+ const payload = bar.payload ?? data[index] ?? {};
34540
+ onClickChartElement?.({
34541
+ ...payload,
34542
+ interactionType: "bar",
34543
+ activeLabel: payload[xAxisField],
34544
+ rowValue: rowValueFromPivotRow(payload, xAxisField),
34545
+ columnValue: elem.field,
34546
+ activeDataKey: elem.field,
34547
+ activeValue: payload[elem.field] ?? bar.value,
34548
+ activePayload: [
34549
+ {
34550
+ dataKey: elem.field,
34551
+ name: elem.label || elem.field,
34552
+ payload,
34553
+ value: payload[elem.field] ?? bar.value
34554
+ }
34555
+ ],
34556
+ category: payload[xAxisField],
34557
+ series: elem.field,
34558
+ value: payload[elem.field] ?? bar.value,
34559
+ row: payload,
34560
+ index
34561
+ });
34562
+ }
34424
34563
  },
34425
34564
  elem.field
34426
34565
  );
@@ -40014,6 +40153,7 @@ var ChartDisplay = ({
40014
40153
  onPageChange,
40015
40154
  onSortChange,
40016
40155
  onClickChartElement,
40156
+ onClickLegendElement,
40017
40157
  overrideTheme,
40018
40158
  referenceLines,
40019
40159
  showLegend,
@@ -40098,6 +40238,7 @@ var ChartDisplay = ({
40098
40238
  theme: overrideTheme ?? theme,
40099
40239
  colorMap,
40100
40240
  onClickChartElement,
40241
+ onClickLegendElement,
40101
40242
  yAxisFields: config?.yAxisFields,
40102
40243
  showLegend: resolvedShowLegend
40103
40244
  }
@@ -40174,6 +40315,7 @@ var ChartDisplay = ({
40174
40315
  hideCartesianGrid,
40175
40316
  colorMap,
40176
40317
  onClickChartElement,
40318
+ onClickLegendElement,
40177
40319
  dateFilter: !hideDateRangeFilter ? dateFilter : void 0,
40178
40320
  referenceLines,
40179
40321
  showLegend: resolvedShowLegend
@@ -40201,6 +40343,7 @@ var ChartDisplay = ({
40201
40343
  hideCartesianGrid,
40202
40344
  colorMap,
40203
40345
  onClickChartElement,
40346
+ onClickLegendElement,
40204
40347
  dateFilter: !hideDateRangeFilter ? dateFilter : void 0,
40205
40348
  referenceLines,
40206
40349
  showLegend: resolvedShowLegend,
@@ -40357,6 +40500,7 @@ var ChartDisplay = ({
40357
40500
  className,
40358
40501
  isAnimationActive,
40359
40502
  onClickChartElement,
40503
+ onClickLegendElement,
40360
40504
  dateFilter: !hideDateRangeFilter ? dateFilter : void 0,
40361
40505
  showLegend: resolvedShowLegend
40362
40506
  }
@@ -40387,6 +40531,7 @@ var ChartDisplay = ({
40387
40531
  comparisonLineStyle: comparisonLineStyle ?? "solid",
40388
40532
  cartesianGridLineColor,
40389
40533
  onClickChartElement,
40534
+ onClickLegendElement,
40390
40535
  dateFilter: !hideDateRangeFilter ? dateFilter : void 0,
40391
40536
  referenceLines,
40392
40537
  showLegend: resolvedShowLegend
@@ -42452,7 +42597,7 @@ function DashboardLegacy({
42452
42597
  const [filterValues, setFilterValues] = useState26({});
42453
42598
  const prevNameRef = useRef15(name2);
42454
42599
  const prevFlagsRef = useRef15(flags);
42455
- const prevClientRef = useRef15(client?.publicKey ?? "");
42600
+ const prevClientRef = useRef15(client?.id ?? "");
42456
42601
  const addFilterPopoverButtonRef = useRef15(null);
42457
42602
  const viewFiltersPopoverButtonRef = useRef15(null);
42458
42603
  const previousFilters = useRef15(filters);
@@ -42508,15 +42653,15 @@ function DashboardLegacy({
42508
42653
  });
42509
42654
  }, [flags]);
42510
42655
  useEffect19(() => {
42511
- if (prevClientRef.current === client?.publicKey) {
42656
+ if (prevClientRef.current === client?.id) {
42512
42657
  return;
42513
42658
  }
42514
- const isInitialKeySet = !prevClientRef.current && client?.publicKey;
42659
+ const isInitialKeySet = !prevClientRef.current && client?.id;
42515
42660
  if (isInitialKeySet && Object.values(data?.sections ?? {}).flat().length) {
42516
- prevClientRef.current = client?.publicKey ?? "";
42661
+ prevClientRef.current = client?.id ?? "";
42517
42662
  return;
42518
42663
  }
42519
- prevClientRef.current = client?.publicKey ?? "";
42664
+ prevClientRef.current = client?.id ?? "";
42520
42665
  if (isClientLoading) {
42521
42666
  return;
42522
42667
  }
@@ -42528,7 +42673,7 @@ function DashboardLegacy({
42528
42673
  prevFlagsRef.current = flags;
42529
42674
  isInitialLoadOfDashboardRef.current = false;
42530
42675
  });
42531
- }, [client?.publicKey]);
42676
+ }, [client?.id]);
42532
42677
  useEffect19(() => {
42533
42678
  setFilterValues(
42534
42679
  Object.values(populatedDashboardFilters ?? {}).reduce((acc, f) => {
@@ -43511,6 +43656,7 @@ function StaticChart(props) {
43511
43656
  const {
43512
43657
  reportId,
43513
43658
  onClickChartElement,
43659
+ onClickLegendElement,
43514
43660
  containerStyle,
43515
43661
  showLegend,
43516
43662
  className
@@ -43563,6 +43709,7 @@ function StaticChart(props) {
43563
43709
  reportId,
43564
43710
  config,
43565
43711
  onClickChartElement,
43712
+ onClickLegendElement,
43566
43713
  loading,
43567
43714
  className,
43568
43715
  containerStyle: safeContainerStyle,
@@ -48664,7 +48811,7 @@ function ChartBuilder({
48664
48811
  task: "dashboard",
48665
48812
  metadata: {
48666
48813
  name: dashboardName,
48667
- clientId: client.clientId,
48814
+ clientId: client.id,
48668
48815
  databaseType: client.databaseType,
48669
48816
  useNewNodeSql: true,
48670
48817
  tenants
@@ -48724,11 +48871,11 @@ function ChartBuilder({
48724
48871
  const getReferencedTables = async (client2, dbTables, sqlQuery, reportBuilderState2, skipStar) => {
48725
48872
  const metadata = reportBuilderState2 ? {
48726
48873
  reportBuilderState: reportBuilderState2,
48727
- clientId: client2.clientId,
48874
+ clientId: client2.id,
48728
48875
  useNewNodeSql: true
48729
48876
  } : {
48730
48877
  query: sqlQuery,
48731
- clientId: client2.clientId,
48878
+ clientId: client2.id,
48732
48879
  useNewNodeSql: true
48733
48880
  };
48734
48881
  try {
@@ -48954,7 +49101,7 @@ function ChartBuilder({
48954
49101
  client,
48955
49102
  task: "dashnames",
48956
49103
  metadata: {
48957
- clientId: client.clientId
49104
+ clientId: client.id
48958
49105
  }
48959
49106
  });
48960
49107
  dashNames = resp.dashboardNames;
@@ -52499,7 +52646,7 @@ function SQLEditor({
52499
52646
  setColumns([]);
52500
52647
  setDisplayTable(false);
52501
52648
  }
52502
- }, [client?.publicKey]);
52649
+ }, [client?.id]);
52503
52650
  useEffect25(() => {
52504
52651
  if (isChartBuilderOpen === false) {
52505
52652
  onCloseChartBuilder && onCloseChartBuilder();
@@ -52758,7 +52905,7 @@ function SQLEditor({
52758
52905
  task: "astify",
52759
52906
  metadata: {
52760
52907
  query: sqlQuery,
52761
- clientId: client2.clientId,
52908
+ clientId: client2.id,
52762
52909
  useNewNodeSql: true
52763
52910
  }
52764
52911
  });
@@ -52951,7 +53098,7 @@ function SQLEditor({
52951
53098
  query: query || "",
52952
53099
  schema: filteredSchema,
52953
53100
  databaseType: client?.databaseType ?? "postgresql",
52954
- clientName: client?.publicKey || "",
53101
+ clientName: client?.id || "",
52955
53102
  setQuery,
52956
53103
  handleRunQuery: () => {
52957
53104
  handleRunQuery(currentProcessing, true);
@@ -55110,7 +55257,7 @@ var useReportBuilderInternal = ({
55110
55257
  !client.featureFlags?.["recommendedPivotsDisabled"]
55111
55258
  );
55112
55259
  }
55113
- if (!initialTableName && !reportId && client.publicKey) {
55260
+ if (!initialTableName && !reportId && client.id) {
55114
55261
  clearAllState();
55115
55262
  }
55116
55263
  }, [client]);
@@ -58665,6 +58812,7 @@ init_valueFormatter();
58665
58812
  // src/utils/queryBuilderFilters.ts
58666
58813
  init_Filter();
58667
58814
  init_reportBuilder();
58815
+ init_dates();
58668
58816
  var buildOperatorOption = (value, label, arity) => ({
58669
58817
  name: value,
58670
58818
  value,
@@ -58833,6 +58981,26 @@ var DATE_UNIT_BY_KEY = {
58833
58981
  day: TimeUnit.Day,
58834
58982
  hour: TimeUnit.Hour
58835
58983
  };
58984
+ var DATE_BUCKETS = /* @__PURE__ */ new Set(["day", "week", "month", "year"]);
58985
+ var parseInBucketValue = (value) => {
58986
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
58987
+ throw new Error(
58988
+ 'inBucket value must be `{ start: string, bucket: "day"|"week"|"month"|"year" }`'
58989
+ );
58990
+ }
58991
+ const record = value;
58992
+ const start = String(record.start ?? "").trim();
58993
+ const bucket = String(record.bucket ?? "").trim().toLowerCase();
58994
+ if (!start) {
58995
+ throw new Error("inBucket value.start is required");
58996
+ }
58997
+ if (!DATE_BUCKETS.has(bucket)) {
58998
+ throw new Error(
58999
+ `inBucket value.bucket must be day|week|month|year (got "${String(record.bucket)}")`
59000
+ );
59001
+ }
59002
+ return { start, bucket };
59003
+ };
58836
59004
  var EMPTY_QUERY_GROUP = {
58837
59005
  combinator: "and",
58838
59006
  rules: []
@@ -59052,6 +59220,17 @@ var internalFilterToRule = (filter) => {
59052
59220
  }
59053
59221
  case "date-custom-filter" /* DateCustomFilter */: {
59054
59222
  const customDate = filter.value;
59223
+ const dateCustom = filter;
59224
+ if (dateCustom.fromInBucket && dateCustom.dateBucket) {
59225
+ return {
59226
+ field,
59227
+ operator: "inBucket",
59228
+ value: {
59229
+ start: customDate.startDate,
59230
+ bucket: dateCustom.dateBucket
59231
+ }
59232
+ };
59233
+ }
59055
59234
  return {
59056
59235
  field,
59057
59236
  operator: "between",
@@ -59236,6 +59415,24 @@ var queryRuleToInternalFilter = (rule, fieldConfigByName) => {
59236
59415
  }
59237
59416
  };
59238
59417
  }
59418
+ if (compactOperatorKey === "inbucket") {
59419
+ const { start, bucket } = parseInBucketValue(rule.value);
59420
+ const range = getExclusiveDateBucketRange(start, bucket);
59421
+ const endInclusive = new Date(Date.parse(range.endExclusive) - 1).toISOString();
59422
+ return {
59423
+ filterType: "date-custom-filter" /* DateCustomFilter */,
59424
+ fieldType: FieldType.Date,
59425
+ operator: DateOperator.Custom,
59426
+ field,
59427
+ table,
59428
+ value: {
59429
+ startDate: range.start,
59430
+ endDate: endInclusive
59431
+ },
59432
+ dateBucket: bucket,
59433
+ fromInBucket: true
59434
+ };
59435
+ }
59239
59436
  const dateComparisonOperator = QUERY_TO_DATE_COMPARISON_OPERATOR[compactOperatorKey] ?? QUERY_TO_DATE_COMPARISON_OPERATOR[operatorKey];
59240
59437
  if (!dateComparisonOperator) {
59241
59438
  throw new Error(`Unsupported date operator "${String(rule.operator)}"`);
@@ -59422,6 +59619,31 @@ var filterStackToQueryBuilderFilters = (filterStack, fieldConfigByName, qualifyA
59422
59619
  ) : base;
59423
59620
  return qualified;
59424
59621
  };
59622
+ var queryBuilderFiltersForEditor = (group) => {
59623
+ const mapEntry = (entry) => {
59624
+ if (isCombinator(entry)) return entry;
59625
+ if (isRuleGroup(entry)) {
59626
+ return queryBuilderFiltersForEditor(entry);
59627
+ }
59628
+ if (!isRule(entry)) return entry;
59629
+ const operator = String(entry.operator ?? "").trim().toLowerCase().replace(/[_\s]+/g, "");
59630
+ if (operator !== "inbucket") return entry;
59631
+ const { start, bucket } = parseInBucketValue(entry.value);
59632
+ const range = getExclusiveDateBucketRange(start, bucket);
59633
+ const endInclusive = new Date(
59634
+ Date.parse(range.endExclusive) - 1
59635
+ ).toISOString();
59636
+ return {
59637
+ ...entry,
59638
+ operator: "between",
59639
+ value: [range.start, endInclusive]
59640
+ };
59641
+ };
59642
+ return {
59643
+ combinator: normalizeCombinator(group.combinator, "and"),
59644
+ rules: (group.rules ?? []).map(mapEntry)
59645
+ };
59646
+ };
59425
59647
  var queryBuilderFiltersToFilterStack = (query, fieldConfigByName) => {
59426
59648
  if (!isRuleGroup(query)) {
59427
59649
  throw new Error("Query must be a rule group");
@@ -59760,6 +59982,37 @@ function useFormReducer(state, action) {
59760
59982
  }
59761
59983
  }
59762
59984
 
59985
+ // src/utils/pivotDateBuckets.ts
59986
+ import {
59987
+ eachDayOfInterval as eachDayOfInterval3,
59988
+ eachMonthOfInterval as eachMonthOfInterval2,
59989
+ eachWeekOfInterval as eachWeekOfInterval2,
59990
+ eachYearOfInterval as eachYearOfInterval2
59991
+ } from "date-fns";
59992
+ function buildPivotDateBucketStarts(range, bucket) {
59993
+ const min2 = new Date(range.min);
59994
+ const max2 = new Date(range.max);
59995
+ if (Number.isNaN(min2.getTime()) || Number.isNaN(max2.getTime())) return [];
59996
+ const start = min2 <= max2 ? min2 : max2;
59997
+ const end = min2 <= max2 ? max2 : min2;
59998
+ const asLocalCalendarDate = (date) => new Date(
59999
+ date.getUTCFullYear(),
60000
+ date.getUTCMonth(),
60001
+ date.getUTCDate(),
60002
+ 12
60003
+ );
60004
+ const interval = {
60005
+ start: asLocalCalendarDate(start),
60006
+ end: asLocalCalendarDate(end)
60007
+ };
60008
+ const dates = bucket === "day" ? eachDayOfInterval3(interval) : bucket === "week" ? eachWeekOfInterval2(interval, { weekStartsOn: 1 }) : bucket === "year" ? eachYearOfInterval2(interval) : eachMonthOfInterval2(interval);
60009
+ return dates.map(
60010
+ (date) => new Date(
60011
+ Date.UTC(date.getFullYear(), date.getMonth(), date.getDate())
60012
+ ).toISOString()
60013
+ );
60014
+ }
60015
+
59763
60016
  // src/hooks/useForm.queries.ts
59764
60017
  var QUERY_KEY_UNDEFINED = "__undefined__";
59765
60018
  var QUERY_KEY_FUNCTION = "__function__";
@@ -59937,52 +60190,6 @@ var AXIS_FORMAT_OPTIONS = [
59937
60190
  { value: "MMM_dd_hh:mm_ap_pm", label: "date and time" },
59938
60191
  { value: "hh_ap_pm", label: "hour" }
59939
60192
  ];
59940
- var USEFORM_FILTERS_DEBUG_FLAG = "__QUILL_DEBUG_USEFORM_FILTERS__";
59941
- var USEFORM_REFRESH_DEBUG_FLAG = "__QUILL_DEBUG_USEFORM_REFRESH__";
59942
- var USEFORM_PIVOT_SHAPE_DEBUG_FLAG = "__QUILL_DEBUG_USEFORM_PIVOT_SHAPE__";
59943
- var isUseFormFiltersDebugEnabled = () => {
59944
- const globalValue = typeof globalThis !== "undefined" ? globalThis?.[USEFORM_FILTERS_DEBUG_FLAG] : void 0;
59945
- if (globalValue === true) {
59946
- return true;
59947
- }
59948
- if (typeof process !== "undefined" && typeof process.env !== "undefined") {
59949
- const envValue = String(
59950
- process?.env?.QUILL_DEBUG_USEFORM_FILTERS ?? ""
59951
- ).trim().toLowerCase();
59952
- return envValue === "1" || envValue === "true";
59953
- }
59954
- return false;
59955
- };
59956
- var isUseFormRefreshDebugEnabled = () => {
59957
- const globalValue = typeof globalThis !== "undefined" ? globalThis?.[USEFORM_REFRESH_DEBUG_FLAG] : void 0;
59958
- if (globalValue === true) {
59959
- return true;
59960
- }
59961
- if (typeof process !== "undefined" && typeof process.env !== "undefined") {
59962
- const envValue = String(
59963
- process?.env?.QUILL_DEBUG_USEFORM_REFRESH ?? ""
59964
- ).trim().toLowerCase();
59965
- return envValue === "1" || envValue === "true";
59966
- }
59967
- return false;
59968
- };
59969
- var isUseFormPivotShapeDebugEnabled = () => {
59970
- const globalValue = typeof globalThis !== "undefined" ? globalThis?.[USEFORM_PIVOT_SHAPE_DEBUG_FLAG] : void 0;
59971
- if (globalValue === true) {
59972
- return true;
59973
- }
59974
- if (typeof process !== "undefined" && typeof process.env !== "undefined") {
59975
- const envValue = String(
59976
- process?.env?.QUILL_DEBUG_USEFORM_PIVOT_SHAPE ?? ""
59977
- ).trim().toLowerCase();
59978
- return envValue === "1" || envValue === "true";
59979
- }
59980
- return false;
59981
- };
59982
- var logUseFormPivotShapeDebug = (label, payload) => {
59983
- if (!isUseFormPivotShapeDebugEnabled()) return;
59984
- console.log(`[useReport][pivot-shape] ${label}`, payload);
59985
- };
59986
60193
  var BOOLEAN_FILTER_VALUE_OPTIONS = [
59987
60194
  { name: "true", label: "True", value: "true" },
59988
60195
  { name: "false", label: "False", value: "false" }
@@ -60450,6 +60657,8 @@ function normalizePivotForRefreshComparison(pivot) {
60450
60657
  const {
60451
60658
  rowFieldTable: _pivotRowTable,
60452
60659
  columnFieldTable: _pivotColumnTable,
60660
+ rowFilter: _rowFilter,
60661
+ columnFilter: _columnFilter,
60453
60662
  aggregations,
60454
60663
  ...pivotRest
60455
60664
  } = record;
@@ -60872,30 +61081,24 @@ function shouldUsePivotRowFieldAsXAxis(chartType, pivotRowField, rowColumnFormat
60872
61081
  function normalizePivotChartForDisplay(chart) {
60873
61082
  const swapPivotRowsForChartRows = Boolean(chart?.pivot) && Array.isArray(chart?.pivotRows) && chart.pivotRows.length > 0;
60874
61083
  const syntheticAggregationOnlyRows = chart && !swapPivotRowsForChartRows ? buildSyntheticAggregationOnlyDisplayRows(chart) : null;
61084
+ const hasExplicitEmptyGroupedPivot = Boolean(
61085
+ String(chart?.pivot?.rowField ?? "").trim() || String(chart?.pivot?.columnField ?? "").trim()
61086
+ ) && Array.isArray(chart?.pivotRows) && chart.pivotRows.length === 0;
60875
61087
  const detailRowsAreNotPivotBuckets = Boolean(chart) && !swapPivotRowsForChartRows && !syntheticAggregationOnlyRows && chartDetailRowsMissingPivotRowBucket(chart);
60876
- logUseFormPivotShapeDebug("normalizePivotChartForDisplay:gate", {
60877
- hasPivot: Boolean(chart?.pivot),
60878
- pivotRowField: chart?.pivot?.rowField,
60879
- pivotRowsIsArray: Array.isArray(chart?.pivotRows),
60880
- pivotRowsLength: Array.isArray(chart?.pivotRows) ? chart.pivotRows.length : null,
60881
- incomingChartRowsLength: Array.isArray(chart?.rows) ? chart.rows.length : null,
60882
- swapPivotRowsForChartRows
60883
- });
60884
61088
  const config = swapPivotRowsForChartRows ? {
60885
61089
  ...chart,
60886
61090
  rows: chart.pivotRows
60887
61091
  } : syntheticAggregationOnlyRows ? {
60888
61092
  ...chart,
60889
61093
  rows: syntheticAggregationOnlyRows
61094
+ } : hasExplicitEmptyGroupedPivot ? {
61095
+ ...chart,
61096
+ rows: []
60890
61097
  } : detailRowsAreNotPivotBuckets ? {
60891
61098
  ...chart,
60892
61099
  rows: []
60893
61100
  } : chart;
60894
61101
  if (!config) return config;
60895
- logUseFormPivotShapeDebug("normalizePivotChartForDisplay:postGateRows", {
60896
- effectiveRowsLength: Array.isArray(config.rows) ? config.rows.length : null,
60897
- stillUsingDetailRows: Boolean(config.pivot) && !swapPivotRowsForChartRows && Array.isArray(config.rows) && config.rows.length > 0
60898
- });
60899
61102
  if (!config.pivot) return config;
60900
61103
  const pivotRowFieldEarly = String(config.pivot?.rowField ?? "").trim();
60901
61104
  const rowColumn = (config.pivotColumns ?? config.columns ?? []).find(
@@ -62059,16 +62262,6 @@ function mergeDisplayAndSourceForTableFormats(args) {
62059
62262
  });
62060
62263
  return { columns, formatByColumnOptionId };
62061
62264
  }
62062
- var USE_FORM_AXIS_SERIES_COLORS = [
62063
- "#6366f1",
62064
- "#f59e0b",
62065
- "#10b981",
62066
- "#ef4444",
62067
- "#8b5cf6",
62068
- "#06b6d4",
62069
- "#f97316",
62070
- "#84cc16"
62071
- ];
62072
62265
  function axisFormatToSelectLabel(format9) {
62073
62266
  const raw = String(format9 ?? "").trim();
62074
62267
  const exact = AXIS_FORMAT_OPTIONS.find((option) => option.value === raw);
@@ -63125,7 +63318,7 @@ async function loadReportForUseForm({
63125
63318
  const hasRowBucketKey = !rowFieldTrimmed || Array.isArray(pivotRows) && pivotRows.some(
63126
63319
  (row) => row && typeof row === "object" && Object.prototype.hasOwnProperty.call(row, rowFieldTrimmed)
63127
63320
  );
63128
- const hasMatchingPivotData = pivotResult.report && !pivotResult.error && Array.isArray(pivotRows) && pivotRows.length > 0 && hasRowBucketKey;
63321
+ const hasMatchingPivotData = pivotResult.report && !pivotResult.error && Array.isArray(pivotRows) && (pivotRows.length === 0 || hasRowBucketKey);
63129
63322
  if (hasMatchingPivotData) {
63130
63323
  return pivotResult;
63131
63324
  }
@@ -63171,7 +63364,6 @@ async function loadReportForUseForm({
63171
63364
  return normalizedBootstrapResult;
63172
63365
  }
63173
63366
  const shouldUseReportTaskForReload = internalFilters.length > 0;
63174
- const resolvedTask = shouldUseReportTaskForReload ? "report" : "item";
63175
63367
  return loadViaInMemoryEngines({
63176
63368
  reportId,
63177
63369
  client,
@@ -63417,8 +63609,6 @@ function useReport(reportIdArg, options = {}) {
63417
63609
  filterStackRef.current = filterStack;
63418
63610
  const resolvedGroupRowsBy = decodePivotGroupOptionValue(groupRowsBy);
63419
63611
  const resolvedGroupColumnsBy = decodePivotGroupOptionValue(groupColumnsBy);
63420
- const useFormRefreshDebugEnabled = isUseFormRefreshDebugEnabled();
63421
- const useFormFiltersDebugEnabled = isUseFormFiltersDebugEnabled();
63422
63612
  useEffect31(() => {
63423
63613
  if (propReportId) {
63424
63614
  setCreatedReportId(null);
@@ -63967,26 +64157,6 @@ function useReport(reportIdArg, options = {}) {
63967
64157
  const filterUniqueValuesEnabled = Boolean(
63968
64158
  client && client?.queryEndpoint && filterUniqueValuesRequest && filterUniqueValuesRequest.stringColumns.length > 0
63969
64159
  );
63970
- useEffect31(() => {
63971
- if (!useFormFiltersDebugEnabled) return;
63972
- const hasClient = Boolean(client);
63973
- const hasQueryEndpoint = Boolean(client?.queryEndpoint);
63974
- const hasRequest = Boolean(filterUniqueValuesRequest);
63975
- const stringColumnsCount = filterUniqueValuesRequest?.stringColumns.length ?? 0;
63976
- const stringColumnsByTableCount = filterUniqueValuesRequest?.stringColumnsByTable.length ?? 0;
63977
- const missingReasons = [];
63978
- if (!hasClient) missingReasons.push("missing-client");
63979
- if (!hasQueryEndpoint) missingReasons.push("missing-query-endpoint");
63980
- if (!hasRequest) missingReasons.push("missing-filterUniqueValuesRequest");
63981
- if (stringColumnsCount === 0) missingReasons.push("no-string-columns");
63982
- }, [
63983
- client,
63984
- filterUniqueValuesEnabled,
63985
- filterUniqueValuesRequest,
63986
- filterUniqueValuesRequestHash,
63987
- effectiveReportId,
63988
- useFormFiltersDebugEnabled
63989
- ]);
63990
64160
  const filterUniqueValuesQuery = useQuery({
63991
64161
  queryKey: [
63992
64162
  "useReport",
@@ -64090,22 +64260,6 @@ function useReport(reportIdArg, options = {}) {
64090
64260
  filterUniqueValuesQuery.data?.uniqueValuesByColumn,
64091
64261
  filterUniqueValuesRequest?.stringColumnsByTable
64092
64262
  ]);
64093
- useEffect31(() => {
64094
- if (!useFormFiltersDebugEnabled) return;
64095
- if (filterUniqueValuesQuery.status !== "success" && filterUniqueValuesQuery.status !== "error") {
64096
- return;
64097
- }
64098
- const uniqueValuesByColumn = filterUniqueValuesQuery.data?.uniqueValuesByColumn ?? {};
64099
- const uniqueValuesByColumnRecord = uniqueValuesByColumn && typeof uniqueValuesByColumn === "object" ? uniqueValuesByColumn : {};
64100
- }, [
64101
- backendUniqueValuesByFieldName,
64102
- filterUniqueValuesEnabled,
64103
- filterUniqueValuesQuery.data,
64104
- filterUniqueValuesQuery.status,
64105
- filterUniqueValuesRequest,
64106
- effectiveReportId,
64107
- useFormFiltersDebugEnabled
64108
- ]);
64109
64263
  const filterValueOptionsByFieldName = useMemo32(() => {
64110
64264
  const optionsByField = /* @__PURE__ */ new Map();
64111
64265
  const selectedMultiselectByField = collectSelectedStringMultiselectValuesByField(queryFilters);
@@ -64868,19 +65022,6 @@ function useReport(reportIdArg, options = {}) {
64868
65022
  resolveCache.set(fieldName, resolved);
64869
65023
  return resolved;
64870
65024
  }
64871
- if (isUseFormFiltersDebugEnabled()) {
64872
- console.error(
64873
- "[useForm-debug] normalizeQueryBuilderFieldNameForConfig ambiguous",
64874
- {
64875
- fieldName,
64876
- candidateKeys: candidates.map(([key]) => key),
64877
- preferredTableNames: Array.from(preferredTableNames),
64878
- primaryTableName,
64879
- effectiveReportBuilderTableNames,
64880
- baseReportBuilderTableNames
64881
- }
64882
- );
64883
- }
64884
65025
  return fieldName;
64885
65026
  };
64886
65027
  }, [
@@ -65272,8 +65413,7 @@ function useReport(reportIdArg, options = {}) {
65272
65413
  }, [
65273
65414
  effectiveReportId,
65274
65415
  tableRefreshQuery.data,
65275
- tableRefreshQueryEnabled,
65276
- useFormRefreshDebugEnabled
65416
+ tableRefreshQueryEnabled
65277
65417
  ]);
65278
65418
  const chartTypes = useMemo32(() => {
65279
65419
  return getChartTypeOptions2({ pivot: pivotState });
@@ -65995,6 +66135,9 @@ function useReport(reportIdArg, options = {}) {
65995
66135
  return {
65996
66136
  ...previousReport,
65997
66137
  ...report,
66138
+ xAxisFormat: previousReport.xAxisFormat,
66139
+ columns: previousReport.columns,
66140
+ yAxisFields: previousReport.yAxisFields,
65998
66141
  pivot: previousReport.pivot,
65999
66142
  pivotRows: previousReport.pivotRows,
66000
66143
  pivotColumns: previousReport.pivotColumns,
@@ -66011,8 +66154,7 @@ function useReport(reportIdArg, options = {}) {
66011
66154
  pivotTableDataRefreshQuery.data,
66012
66155
  pivotTableDataRefreshQuery.status,
66013
66156
  pivotTableDataRefreshQueryEnabled,
66014
- effectiveReportId,
66015
- useFormRefreshDebugEnabled
66157
+ effectiveReportId
66016
66158
  ]);
66017
66159
  useEffect31(() => {
66018
66160
  if (!pivotRefreshQueryEnabled) return;
@@ -66064,8 +66206,7 @@ function useReport(reportIdArg, options = {}) {
66064
66206
  pivotRefreshQuery.data,
66065
66207
  pivotRefreshQuery.status,
66066
66208
  pivotRefreshQueryEnabled,
66067
- effectiveReportId,
66068
- useFormRefreshDebugEnabled
66209
+ effectiveReportId
66069
66210
  ]);
66070
66211
  const chartData = useMemo32(() => {
66071
66212
  if (!sourceReport) return void 0;
@@ -66073,8 +66214,8 @@ function useReport(reportIdArg, options = {}) {
66073
66214
  const chartPivotForDisplay = nextPivot ?? (!chartPivotHydratedFromSourceRef.current ? sourceReport.pivot ?? null : null);
66074
66215
  const rowCountForChart = chartPivotForDisplay ? sourceReport.pivotRowCount ?? (Array.isArray(sourceReport.pivotRows) ? sourceReport.pivotRows.length : sourceReport.rowCount) : useInMemoryEngines ? rowsForChart.length : sourceReport.rowCount;
66075
66216
  const referencedTablesForChart = effectiveReportBuilderState?.tables.map((table2) => table2.name).filter((name2) => Boolean(name2));
66076
- const pivotRowsForChart = Array.isArray(sourceReport.pivotRows) && sourceReport.pivotRows.length > 0 ? sourceReport.pivotRows : [];
66077
- const rowCountForChartResolved = chartPivotForDisplay ? pivotRowsForChart.length > 0 ? pivotRowsForChart.length : rowCountForChart : rowCountForChart;
66217
+ const pivotRowsForChart = Array.isArray(sourceReport.pivotRows) ? sourceReport.pivotRows : void 0;
66218
+ const rowCountForChartResolved = chartPivotForDisplay ? Array.isArray(pivotRowsForChart) ? pivotRowsForChart.length : rowCountForChart : rowCountForChart;
66078
66219
  const chartDataPayload = {
66079
66220
  ...sourceReport,
66080
66221
  rows: rowsForChart,
@@ -66085,15 +66226,8 @@ function useReport(reportIdArg, options = {}) {
66085
66226
  referencedTables: referencedTablesForChart && referencedTablesForChart.length > 0 ? referencedTablesForChart : sourceReport.referencedTables,
66086
66227
  pivotRows: pivotRowsForChart,
66087
66228
  pivotColumns: sourceReport.pivotColumns,
66088
- pivotRowCount: pivotRowsForChart.length
66229
+ pivotRowCount: Array.isArray(pivotRowsForChart) ? pivotRowsForChart.length : sourceReport.pivotRowCount
66089
66230
  };
66090
- logUseFormPivotShapeDebug("chartData:memo", {
66091
- reportId: sourceReport.id,
66092
- detailRowsLength: rowsForChart.length,
66093
- pivotRowsIsArray: Array.isArray(sourceReport.pivotRows),
66094
- pivotRowsLength: Array.isArray(sourceReport.pivotRows) ? sourceReport.pivotRows.length : null,
66095
- hasNextPivot: Boolean(nextPivot)
66096
- });
66097
66231
  return chartDataPayload;
66098
66232
  }, [
66099
66233
  sourceReport,
@@ -66131,8 +66265,8 @@ function useReport(reportIdArg, options = {}) {
66131
66265
  for (const column of chartAxesBaseChart.columns ?? []) {
66132
66266
  registerOption(column.field, column.label, column.format);
66133
66267
  }
66134
- for (const yAxis of chartAxesBaseChart.yAxisFields ?? []) {
66135
- registerOption(yAxis.field, yAxis.label, yAxis.format);
66268
+ for (const yAxis2 of chartAxesBaseChart.yAxisFields ?? []) {
66269
+ registerOption(yAxis2.field, yAxis2.label, yAxis2.format);
66136
66270
  }
66137
66271
  if (chartAxesBaseChart.pivot?.columnField) {
66138
66272
  for (const aggregationAxis of buildPivotAggregationAxisFields(
@@ -66355,48 +66489,35 @@ function useReport(reportIdArg, options = {}) {
66355
66489
  }),
66356
66490
  [baseChart?.showLegend, chartVisibilityOverrides]
66357
66491
  );
66358
- const axisConfig = useMemo32(() => {
66492
+ const xAxis = useMemo32(() => {
66359
66493
  const pivotBucketXAxis = isPivotTableDateBucketRowAxis(
66360
66494
  chartAxesBaseChart,
66361
66495
  resolvedXAxisField
66362
66496
  );
66363
66497
  const xFormatLabel = pivotBucketXAxis && String(resolvedXAxisFormat ?? "").trim() === "string" ? "date" : axisFormatToSelectLabel(resolvedXAxisFormat);
66364
66498
  return {
66365
- xAxis: {
66366
- field: resolvedXAxisField,
66367
- label: resolvedXAxisLabel,
66368
- format: xFormatLabel,
66369
- show: true,
66370
- rotation: 0,
66371
- fontSize: 12
66372
- },
66373
- yAxis: {
66374
- fields: resolvedYAxisFields.map((yAxisField, index) => ({
66375
- field: yAxisField.field,
66376
- label: String(yAxisField.label ?? "").trim(),
66377
- format: axisFormatToSelectLabel(
66378
- toAxisFormat(yAxisField.format, "string")
66379
- ),
66380
- color: USE_FORM_AXIS_SERIES_COLORS[index % USE_FORM_AXIS_SERIES_COLORS.length]
66381
- })),
66382
- label: "",
66383
- show: true,
66384
- min: "",
66385
- max: "",
66386
- fontSize: 12
66387
- },
66388
- legend: {
66389
- show: chartVisibility.showLegend
66390
- }
66499
+ field: resolvedXAxisField,
66500
+ label: resolvedXAxisLabel,
66501
+ format: xFormatLabel
66391
66502
  };
66392
66503
  }, [
66393
66504
  chartAxesBaseChart,
66394
66505
  resolvedXAxisLabel,
66395
66506
  resolvedXAxisField,
66396
- resolvedXAxisFormat,
66397
- resolvedYAxisFields,
66398
- chartVisibility.showLegend
66507
+ resolvedXAxisFormat
66399
66508
  ]);
66509
+ const yAxis = useMemo32(
66510
+ () => ({
66511
+ fields: resolvedYAxisFields.map((yAxisField) => ({
66512
+ field: yAxisField.field,
66513
+ label: String(yAxisField.label ?? "").trim(),
66514
+ format: axisFormatToSelectLabel(
66515
+ toAxisFormat(yAxisField.format, "string")
66516
+ )
66517
+ }))
66518
+ }),
66519
+ [resolvedYAxisFields]
66520
+ );
66400
66521
  const resolvedYAxisFieldsForDisplay = useMemo32(() => {
66401
66522
  if (!baseChart) return resolvedYAxisFields;
66402
66523
  return mapResolvedPivotYAxisFieldsForDisplay({
@@ -66418,26 +66539,6 @@ function useReport(reportIdArg, options = {}) {
66418
66539
  xAxisLabel: resolvedXAxisLabel
66419
66540
  });
66420
66541
  }
66421
- logUseFormPivotShapeDebug("chart:formatting(yAxis+pivotColumns)", {
66422
- chartType: baseChart.chartType,
66423
- pivotRowField: baseChart.pivot?.rowField,
66424
- xAxisField: resolvedXAxisField,
66425
- xAxisFormat: resolvedXAxisFormat,
66426
- yAxisFieldsForDisplay: (resolvedYAxisFieldsForDisplay ?? []).map((y) => ({
66427
- field: y.field,
66428
- format: y.format,
66429
- label: y.label
66430
- })),
66431
- pivotColumnsSample: (baseChart.pivotColumns ?? []).slice(0, 12).map((c) => ({
66432
- field: c.field,
66433
- format: c.format,
66434
- label: c.label
66435
- })),
66436
- mergedColumnFormatsSample: (columns2 ?? baseChart.columns ?? []).slice(0, 12).map((c) => ({
66437
- field: c.field,
66438
- format: c.format
66439
- }))
66440
- });
66441
66542
  return {
66442
66543
  ...baseChart,
66443
66544
  xAxisField: resolvedXAxisField,
@@ -66453,6 +66554,144 @@ function useReport(reportIdArg, options = {}) {
66453
66554
  resolvedXAxisLabel,
66454
66555
  resolvedYAxisFieldsForDisplay
66455
66556
  ]);
66557
+ const pivotDateFilterRangeCacheRef = useRef24({ key: "", min: null, max: null });
66558
+ const filterOptions = useMemo32(() => {
66559
+ const out = [];
66560
+ for (const [field, values] of filterValueOptionsByFieldName) {
66561
+ out.push({
66562
+ field,
66563
+ fieldType: "string",
66564
+ operator: "in",
66565
+ options: values.map(({ label, value }) => ({ label, value }))
66566
+ });
66567
+ }
66568
+ const pivot = chart?.pivot;
66569
+ const rowField = String(pivot?.rowField ?? "").trim();
66570
+ if (rowField && isDateType(String(pivot?.rowFieldType ?? ""))) {
66571
+ const field = pivot?.rowFieldTable ? `${pivot.rowFieldTable}.${rowField}` : rowField;
66572
+ const bucket = dateBucket || pivot?.dateBucket || "month";
66573
+ const labelsByRaw = /* @__PURE__ */ new Map();
66574
+ const cacheKey = `${String(effectiveReportId ?? "")}\0${field}\0${bucket}`;
66575
+ if (pivotDateFilterRangeCacheRef.current.key !== cacheKey) {
66576
+ pivotDateFilterRangeCacheRef.current = {
66577
+ key: cacheKey,
66578
+ min: null,
66579
+ max: null
66580
+ };
66581
+ }
66582
+ for (const row of chart?.rows ?? []) {
66583
+ const record = row;
66584
+ const raw = record.__quillRawDate;
66585
+ if (raw == null || raw === "") continue;
66586
+ const key = String(raw);
66587
+ const timestamp = new Date(key).getTime();
66588
+ if (Number.isNaN(timestamp)) continue;
66589
+ labelsByRaw.set(key, String(record[rowField] ?? key));
66590
+ const cachedMin = pivotDateFilterRangeCacheRef.current.min;
66591
+ const cachedMax = pivotDateFilterRangeCacheRef.current.max;
66592
+ if (cachedMin == null || timestamp < new Date(cachedMin).getTime()) {
66593
+ pivotDateFilterRangeCacheRef.current.min = key;
66594
+ }
66595
+ if (cachedMax == null || timestamp > new Date(cachedMax).getTime()) {
66596
+ pivotDateFilterRangeCacheRef.current.max = key;
66597
+ }
66598
+ }
66599
+ const { min: min2, max: max2 } = pivotDateFilterRangeCacheRef.current;
66600
+ const options2 = min2 && max2 ? buildPivotDateBucketStarts({ min: min2, max: max2 }, bucket).map((value) => ({
66601
+ value,
66602
+ label: labelsByRaw.get(value) ?? getDateString(value, void 0, bucket)
66603
+ })) : [];
66604
+ out.push({
66605
+ field,
66606
+ fieldType: "date",
66607
+ operator: "inBucket",
66608
+ dateBucket: bucket,
66609
+ options: options2
66610
+ });
66611
+ }
66612
+ return out;
66613
+ }, [
66614
+ chart?.pivot,
66615
+ chart?.rows,
66616
+ dateBucket,
66617
+ effectiveReportId,
66618
+ filterValueOptionsByFieldName
66619
+ ]);
66620
+ const chartForUi = useMemo32(() => {
66621
+ if (!chart?.pivot) return chart;
66622
+ const pivot = chart.pivot;
66623
+ const qualify = (field, table2) => table2 ? `${table2}.${field}` : field;
66624
+ const labelFor = (field) => chart.columns?.find((column) => column.field === field)?.label ?? field.split(".").pop().replace(/[_-]+/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
66625
+ const matchField = (entryField, field, table2) => {
66626
+ const qualified = qualify(field, table2);
66627
+ return entryField === qualified || entryField === field || entryField.endsWith(`.${field}`);
66628
+ };
66629
+ const selectedValue = (field, operator, options2) => {
66630
+ const rule = filtersForQueryBuilder.rules.find(
66631
+ (entry) => typeof entry === "object" && entry !== null && "field" in entry && entry.field === field && entry.operator === operator
66632
+ );
66633
+ if (!rule) return null;
66634
+ const raw = operator === "inBucket" ? rule.value?.start : Array.isArray(rule.value) ? rule.value[0] : void 0;
66635
+ if (raw == null) return null;
66636
+ const value = String(raw);
66637
+ return options2.some((option) => option.value === value) ? value : null;
66638
+ };
66639
+ let rowFilter = null;
66640
+ const rowField = String(pivot.rowField ?? "").trim();
66641
+ if (rowField) {
66642
+ if (isDateType(String(pivot.rowFieldType ?? ""))) {
66643
+ const entry = filterOptions.find(
66644
+ (option) => option.operator === "inBucket" && matchField(option.field, rowField, pivot.rowFieldTable)
66645
+ );
66646
+ if (entry) {
66647
+ const field = qualify(rowField, pivot.rowFieldTable);
66648
+ rowFilter = {
66649
+ ...entry,
66650
+ field,
66651
+ label: labelFor(rowField),
66652
+ value: selectedValue(field, entry.operator, entry.options)
66653
+ };
66654
+ }
66655
+ } else {
66656
+ const entry = filterOptions.find(
66657
+ (option) => option.operator === "in" && matchField(option.field, rowField, pivot.rowFieldTable)
66658
+ );
66659
+ if (entry) {
66660
+ const field = qualify(rowField, pivot.rowFieldTable);
66661
+ rowFilter = {
66662
+ ...entry,
66663
+ field,
66664
+ label: labelFor(rowField),
66665
+ value: selectedValue(field, entry.operator, entry.options)
66666
+ };
66667
+ }
66668
+ }
66669
+ }
66670
+ let columnFilter = null;
66671
+ const columnField = String(pivot.columnField ?? "").trim();
66672
+ if (columnField) {
66673
+ const entry = filterOptions.find(
66674
+ (option) => option.operator === "in" && matchField(option.field, columnField, pivot.columnFieldTable)
66675
+ );
66676
+ if (entry) {
66677
+ const field = qualify(columnField, pivot.columnFieldTable);
66678
+ columnFilter = {
66679
+ ...entry,
66680
+ field,
66681
+ label: labelFor(columnField),
66682
+ value: selectedValue(field, entry.operator, entry.options)
66683
+ };
66684
+ }
66685
+ }
66686
+ return {
66687
+ ...chart,
66688
+ pivot: {
66689
+ ...pivot,
66690
+ rowFilter,
66691
+ columnFilter
66692
+ }
66693
+ };
66694
+ }, [chart, filterOptions, filtersForQueryBuilder]);
66456
66695
  const isPivotTableChart = String(chartType ?? "").toLowerCase() === "table" && Boolean(
66457
66696
  chart && chart.pivot && Array.isArray(chart.columns) && chart.columns.length > 0
66458
66697
  );
@@ -66783,14 +67022,6 @@ function useReport(reportIdArg, options = {}) {
66783
67022
  schemaColumnOptions,
66784
67023
  table.columns
66785
67024
  ]);
66786
- const availableFields = useMemo32(
66787
- () => tableColumnPickerPoolOptions.map((option) => ({
66788
- id: option.value,
66789
- label: option.label,
66790
- type: option.type
66791
- })),
66792
- [tableColumnPickerPoolOptions]
66793
- );
66794
67025
  const axisSelectFormatLabels = useMemo32(
66795
67026
  () => AXIS_FORMAT_OPTIONS.map((option) => option.label),
66796
67027
  []
@@ -67236,8 +67467,12 @@ function useReport(reportIdArg, options = {}) {
67236
67467
  showLegend: Boolean(effectiveNextState.showLegend)
67237
67468
  }));
67238
67469
  }
67239
- if (effectiveNextState.chartAxes !== void 0) {
67240
- const cx = effectiveNextState.chartAxes;
67470
+ if (effectiveNextState.xAxis !== void 0 || effectiveNextState.yAxis !== void 0 || effectiveNextState.chartAxes !== void 0) {
67471
+ const cx = {
67472
+ ...effectiveNextState.chartAxes,
67473
+ ...effectiveNextState.xAxis !== void 0 ? { xAxis: effectiveNextState.xAxis } : {},
67474
+ ...effectiveNextState.yAxis !== void 0 ? { yAxis: effectiveNextState.yAxis } : {}
67475
+ };
67241
67476
  setChartAxisEdits((previousEdits) => {
67242
67477
  const nextEdits = { ...previousEdits };
67243
67478
  if (cx.xAxis) {
@@ -67757,8 +67992,9 @@ function useReport(reportIdArg, options = {}) {
67757
67992
  }
67758
67993
  };
67759
67994
  const setFilters = (nextFilters) => {
67995
+ const resolved = typeof nextFilters === "function" ? nextFilters(filtersForQueryBuilder) : nextFilters;
67760
67996
  const preparedForStack = prepareQueryBuilderFiltersForSet(
67761
- nextFilters,
67997
+ resolved,
67762
67998
  queryFilters
67763
67999
  );
67764
68000
  const nextFiltersNormalizedForConfig = normalizeQueryBuilderFiltersForConfig(preparedForStack);
@@ -67799,17 +68035,17 @@ function useReport(reportIdArg, options = {}) {
67799
68035
  });
67800
68036
  }
67801
68037
  } catch (error) {
67802
- if (isUseFormFiltersDebugEnabled()) {
67803
- console.error("[useForm-debug] setFilters swallowed error", {
67804
- error: error instanceof Error ? error.message : String(error),
67805
- requestedRules: (nextFilters?.rules ?? []).map((rule) => ({
67806
- table: rule?.table,
67807
- field: rule?.field,
67808
- operator: rule?.operator
67809
- })),
67810
- fieldConfigKeys: Object.keys(queryBuilderFieldConfigByName ?? {})
67811
- });
67812
- }
68038
+ console.error("[useForm] setFilters swallowed error", {
68039
+ error: error instanceof Error ? error.message : String(error),
68040
+ stack: error instanceof Error ? error.stack : void 0,
68041
+ requestedRules: (resolved?.rules ?? []).map((rule) => ({
68042
+ table: rule?.table,
68043
+ field: rule?.field,
68044
+ operator: rule?.operator,
68045
+ value: rule?.value
68046
+ })),
68047
+ fieldConfigKeys: Object.keys(queryBuilderFieldConfigByName ?? {})
68048
+ });
67813
68049
  }
67814
68050
  };
67815
68051
  const saveChanges = useCallback5(async () => {
@@ -67871,7 +68107,7 @@ function useReport(reportIdArg, options = {}) {
67871
68107
  ]);
67872
68108
  return {
67873
68109
  /* ── Chart & table (exceptions: not value/options pairs) ── */
67874
- chart,
68110
+ chart: chartForUi,
67875
68111
  chartLoading,
67876
68112
  table,
67877
68113
  tableLoading,
@@ -67909,9 +68145,9 @@ function useReport(reportIdArg, options = {}) {
67909
68145
  columnActions,
67910
68146
  /** Schema columns for current datasources — pool for the table column picker. */
67911
68147
  columnOptions: tableColumnPickerPoolOptions,
67912
- xAxis: chartAxes.xAxis,
68148
+ xAxis,
67913
68149
  xAxisOptions: normalizedChartXAxisOptions,
67914
- yAxis: chartAxes.yAxis,
68150
+ yAxis,
67915
68151
  yAxisOptions: normalizedChartYAxisOptions,
67916
68152
  /** Same strings as `axisSelectFormatLabels` (X/Y share chart format presets). */
67917
68153
  xAxisFormatOptions: xAxisFormatOptionLabels,
@@ -67919,8 +68155,6 @@ function useReport(reportIdArg, options = {}) {
67919
68155
  /** Table column format dropdown labels (same set as chart axis formats). */
67920
68156
  tableFormatOptions: axisSelectFormatLabels,
67921
68157
  showLegend: chartVisibility.showLegend,
67922
- axisConfig,
67923
- availableFields,
67924
68158
  axisSelectFormatLabels,
67925
68159
  /** @deprecated Prefer top-level `xAxis`, `yAxis`, and `showLegend`. */
67926
68160
  chartAxes,
@@ -67933,6 +68167,12 @@ function useReport(reportIdArg, options = {}) {
67933
68167
  hasTableDrivenColumnOrder,
67934
68168
  filters: filtersForQueryBuilder,
67935
68169
  filterQueryBuilderProps,
68170
+ /**
68171
+ * Filter value pick lists for custom UIs (string unique values + pivot date
68172
+ * buckets). Same string data as `filterQueryBuilderProps.getValues`; not
68173
+ * wired into react-querybuilder unless you use it yourself.
68174
+ */
68175
+ filterOptions,
67936
68176
  /** True while `report-builder-unique-values` runs for filter value options (not chart/table load). */
67937
68177
  filterUniqueValuesLoading,
67938
68178
  limit,
@@ -68313,11 +68553,11 @@ function Chat({
68313
68553
  setIsLoading(false);
68314
68554
  };
68315
68555
  const submitDefaultMessage = async (nextMessages, abortController) => {
68316
- const clientId = client.clientId ?? client.publicKey;
68556
+ const clientId = client.id;
68317
68557
  let responseBuffer = "";
68318
68558
  for await (const chunk of quillStream({
68319
68559
  client: {
68320
- clientId,
68560
+ id: clientId,
68321
68561
  queryEndpoint: client.queryEndpoint,
68322
68562
  streamEndpoint: client.streamEndpoint,
68323
68563
  queryHeaders: client.queryHeaders,
@@ -68401,12 +68641,12 @@ function Chat({
68401
68641
  }
68402
68642
  };
68403
68643
  const submitAgentMessage = async (nextMessages, abortController) => {
68404
- const clientId = client.clientId ?? client.publicKey;
68644
+ const clientId = client.id;
68405
68645
  let updatedMessages = [...nextMessages];
68406
68646
  for await (const event of quillAgentStream({
68407
68647
  endpoint: `${agentEndpoint}/agent/chat`,
68408
68648
  messages: updatedMessages,
68409
- sourceClientId: clientId,
68649
+ sourceClientId: clientId ?? "<unknown>",
68410
68650
  getToken,
68411
68651
  abortSignal: abortController.signal
68412
68652
  })) {
@@ -68474,7 +68714,7 @@ function Chat({
68474
68714
  setIsLoading(true);
68475
68715
  const abortController = new AbortController();
68476
68716
  abortControllerRef.current = abortController;
68477
- const clientId = client.clientId ?? client.publicKey;
68717
+ const clientId = client.id;
68478
68718
  if (!clientId) {
68479
68719
  setInputError("No client selected.");
68480
68720
  setIsLoading(false);
@@ -68771,7 +69011,9 @@ var committedFiltersSignature = (committed) => {
68771
69011
  };
68772
69012
  function useReportFilterDraft(args) {
68773
69013
  const { reportId, committedFilters, queryBuilderProps, setFilters } = args;
68774
- const committed = isQueryBuilderDisplayGroup(committedFilters) ? committedFilters : EMPTY_COMMITTED_FILTERS;
69014
+ const committed = queryBuilderFiltersForEditor(
69015
+ isQueryBuilderDisplayGroup(committedFilters) ? committedFilters : EMPTY_COMMITTED_FILTERS
69016
+ );
68775
69017
  const committedRef = useRef26(committed);
68776
69018
  committedRef.current = committed;
68777
69019
  const setFiltersRef = useRef26(setFilters);
@@ -68826,6 +69068,12 @@ function useReportFilterDraft(args) {
68826
69068
  setHasUnappliedFilterChanges(false);
68827
69069
  setResetEpoch((epoch) => epoch + 1);
68828
69070
  }, []);
69071
+ const getDefaultField = useCallback6((fields) => {
69072
+ const stringField = fields.find(
69073
+ (field) => field.quillFieldType === "string" && String(field.name ?? "").trim()
69074
+ );
69075
+ return stringField?.name ?? fields[0]?.name ?? "";
69076
+ }, []);
68829
69077
  const getDefaultValue = useCallback6(
68830
69078
  (rule) => defaultFilterRuleValueForOperator(rule?.operator),
68831
69079
  []
@@ -68836,9 +69084,12 @@ function useReportFilterDraft(args) {
68836
69084
  fields: effectiveFields,
68837
69085
  // Uncontrolled: react-querybuilder owns the draft; only read at mount,
68838
69086
  // while state keeps the next mount hydrated from the latest edits.
68839
- defaultQuery: draftQuery,
69087
+ // Empty draft: omit defaultQuery so addRuleToNewGroups seeds a root rule
69088
+ // (RQB ignores auto-add when defaultQuery.rules is []).
69089
+ ...draftQuery.rules.length > 0 ? { defaultQuery: draftQuery } : {},
68840
69090
  onQueryChange: handleQueryChange,
68841
69091
  addRuleToNewGroups: true,
69092
+ getDefaultField,
68842
69093
  getDefaultValue
68843
69094
  }),
68844
69095
  // eslint-disable-next-line react-hooks/exhaustive-deps -- filterDraftKey covers draftRef resets
@@ -68847,6 +69098,7 @@ function useReportFilterDraft(args) {
68847
69098
  effectiveFields,
68848
69099
  draftQuery,
68849
69100
  handleQueryChange,
69101
+ getDefaultField,
68850
69102
  getDefaultValue,
68851
69103
  filterDraftKey
68852
69104
  ]
@@ -69735,7 +69987,7 @@ var useVirtualTables = () => {
69735
69987
  };
69736
69988
  };
69737
69989
  const handleRefreshSome = async (client, tables) => {
69738
- if (!client.clientId) return schemaData;
69990
+ if (!client.id) return schemaData;
69739
69991
  setLoadingTables({
69740
69992
  ...loadingTables,
69741
69993
  ...tables.reduce((acc, table) => {
@@ -69753,7 +70005,7 @@ var useVirtualTables = () => {
69753
70005
  name: table.name,
69754
70006
  customFieldInfo: table.customFieldInfo,
69755
70007
  id: table._id,
69756
- clientId: client.clientId,
70008
+ clientId: client.id,
69757
70009
  runQueryConfig: { getColumns: true },
69758
70010
  databaseType: client.databaseType,
69759
70011
  useNewNodeSql: true
@@ -69901,11 +70153,12 @@ var useChangelogRefresh = () => {
69901
70153
  reportsDispatch({ type: "DELETE_REPORT", id: reportId });
69902
70154
  dashboardDispatch({ type: "REMOVE_DASHBOARD_ITEM", id: reportId });
69903
70155
  }
69904
- const finalDashboardSet = reloadAllDashboards ? new Set(
69905
- Object.keys(dashboardConfig).filter(
70156
+ const finalDashboardSet = reloadAllDashboards ? /* @__PURE__ */ new Set([
70157
+ ...Object.keys(dashboardConfig).filter(
69906
70158
  (d) => !dashboardsToRemove.has(d)
69907
- )
69908
- ) : dashboardsToReload;
70159
+ ),
70160
+ ...dashboardsToReload
70161
+ ]) : dashboardsToReload;
69909
70162
  const tasks = [];
69910
70163
  const schemaIdsToReload = schemaIds.filter(
69911
70164
  (id) => !schemaIdsToRemove.has(id)
@@ -70020,6 +70273,7 @@ export {
70020
70273
  isQueryBuilderDisplayRule,
70021
70274
  normalizeRelativeDateRules,
70022
70275
  prepareQueryBuilderFiltersForSet,
70276
+ queryBuilderFiltersForEditor,
70023
70277
  quillFetch,
70024
70278
  stripQueryBuilderTransientFields,
70025
70279
  tableColumnFormatFromUiSelection,