deepspotscreen-sdk 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,24 +1,24 @@
1
- class S {
1
+ class K {
2
2
  constructor(e, t) {
3
3
  this.tokenCache = /* @__PURE__ */ new Map(), this.baseUrl = e.replace(/\/$/, ""), this.apiKey = t;
4
4
  }
5
5
  // ── Embed Token ─────────────────────────────────────────────────────────────
6
6
  async getEmbedToken(e) {
7
- var i, a, d, o;
7
+ var r, a, o, l;
8
8
  const t = [
9
9
  e.dashboardId,
10
10
  e.embedType,
11
- (i = e.embedLevel) != null ? i : "",
11
+ (r = e.embedLevel) != null ? r : "",
12
12
  (a = e.componentId) != null ? a : "",
13
- (d = e.userId) != null ? d : ""
13
+ (o = e.userId) != null ? o : ""
14
14
  ].join(":"), s = this.tokenCache.get(t);
15
15
  if (s && s.expiresAt > Date.now() + 6e4) return s.token;
16
- const r = await this.post(
16
+ const i = await this.post(
17
17
  "/dashboard-builder/embed-token",
18
18
  {
19
19
  dashboardId: e.dashboardId,
20
20
  embedType: e.embedType,
21
- embedLevel: (o = e.embedLevel) != null ? o : "dashboard",
21
+ embedLevel: (l = e.embedLevel) != null ? l : "dashboard",
22
22
  componentId: e.componentId,
23
23
  userId: e.userId,
24
24
  tenantId: e.tenantId,
@@ -27,35 +27,35 @@ class S {
27
27
  { "x-deepspot-api-key": this.apiKey }
28
28
  );
29
29
  return this.tokenCache.set(t, {
30
- token: r.token,
31
- expiresAt: new Date(r.expiresAt).getTime()
32
- }), r.token;
30
+ token: i.token,
31
+ expiresAt: new Date(i.expiresAt).getTime()
32
+ }), i.token;
33
33
  }
34
34
  // ── Dashboard Render (lazy — loads one tab at a time) ──────────────────────
35
35
  async getDashboardRender(e, t, s = {}) {
36
- var i;
37
- const r = new URLSearchParams({
36
+ var r;
37
+ const i = new URLSearchParams({
38
38
  embedType: "dashboard",
39
- embedLevel: (i = s.embedLevel) != null ? i : "dashboard"
39
+ embedLevel: (r = s.embedLevel) != null ? r : "dashboard"
40
40
  });
41
- return s.pageId && r.set("pageId", s.pageId), s.tabId && r.set("tabId", s.tabId), s.filters && Object.entries(s.filters).forEach(([a, d]) => {
42
- d != null && d !== "" && r.set(`filter[${a}]`, Array.isArray(d) ? d.join(",") : String(d));
41
+ return s.pageId && i.set("pageId", s.pageId), s.tabId && i.set("tabId", s.tabId), s.filters && Object.entries(s.filters).forEach(([a, o]) => {
42
+ o != null && o !== "" && i.set(`filter[${a}]`, Array.isArray(o) ? o.join(",") : String(o));
43
43
  }), this.get(
44
- `/dashboard-builder/embed/${e}/render?${r}`,
44
+ `/dashboard-builder/embed/${e}/render?${i}`,
45
45
  { "x-embed-token": t }
46
46
  );
47
47
  }
48
48
  // ── Single Report Render ────────────────────────────────────────────────────
49
- async getReportRender(e, t, s, r = {}) {
50
- const i = new URLSearchParams({
49
+ async getReportRender(e, t, s, i = {}) {
50
+ const r = new URLSearchParams({
51
51
  embedType: "report",
52
52
  embedLevel: "report",
53
53
  componentId: t
54
54
  });
55
- return r.filters && Object.entries(r.filters).forEach(([a, d]) => {
56
- d != null && d !== "" && i.set(`filter[${a}]`, Array.isArray(d) ? d.join(",") : String(d));
55
+ return i.filters && Object.entries(i.filters).forEach(([a, o]) => {
56
+ o != null && o !== "" && r.set(`filter[${a}]`, Array.isArray(o) ? o.join(",") : String(o));
57
57
  }), this.get(
58
- `/dashboard-builder/embed/${e}/render?${i}`,
58
+ `/dashboard-builder/embed/${e}/render?${r}`,
59
59
  { "x-embed-token": s }
60
60
  );
61
61
  }
@@ -75,6 +75,18 @@ class S {
75
75
  Authorization: `Bearer ${t}`
76
76
  });
77
77
  }
78
+ // ── Paginated Table Data ────────────────────────────────────────────────────
79
+ /**
80
+ * Fetches one page of data for an embedded data-table component.
81
+ * Called by TableRenderer whenever the user navigates to a different page.
82
+ * Mirrors: GET /dashboard-builder/embed/:dashboardId/table/:componentId/data
83
+ */
84
+ async getTablePage(e, t, s, i, r) {
85
+ return this.get(
86
+ `/dashboard-builder/embed/${e}/table/${t}/data?page=${s}&pageSize=${i}`,
87
+ { "x-embed-token": r }
88
+ );
89
+ }
78
90
  // ── Filter Options ──────────────────────────────────────────────────────────
79
91
  /**
80
92
  * Fetches distinct option values for a dropdown / multi-select filter.
@@ -85,12 +97,12 @@ class S {
85
97
  */
86
98
  async getFilterOptions(e, t, s) {
87
99
  try {
88
- const r = await this.get(
100
+ const i = await this.get(
89
101
  `/dashboard-builder/embed/${e}/filters/${t}/options`,
90
102
  { "x-embed-token": s }
91
103
  );
92
- return Array.isArray(r) ? r : Array.isArray(r == null ? void 0 : r.options) ? r.options : Array.isArray(r == null ? void 0 : r.data) ? r.data : [];
93
- } catch (r) {
104
+ return Array.isArray(i) ? i : Array.isArray(i == null ? void 0 : i.options) ? i.options : Array.isArray(i == null ? void 0 : i.data) ? i.data : [];
105
+ } catch (i) {
94
106
  return [];
95
107
  }
96
108
  }
@@ -106,12 +118,12 @@ class S {
106
118
  return this.handleResponse(s);
107
119
  }
108
120
  async post(e, t, s = {}) {
109
- const r = await fetch(`${this.baseUrl}${e}`, {
121
+ const i = await fetch(`${this.baseUrl}${e}`, {
110
122
  method: "POST",
111
123
  headers: { "Content-Type": "application/json", ...s },
112
124
  body: JSON.stringify(t)
113
125
  });
114
- return this.handleResponse(r);
126
+ return this.handleResponse(i);
115
127
  }
116
128
  async delete(e, t = {}) {
117
129
  const s = await fetch(`${this.baseUrl}${e}`, {
@@ -124,9 +136,9 @@ class S {
124
136
  if (!e.ok) {
125
137
  let s = `HTTP ${e.status}`;
126
138
  try {
127
- const r = await e.json();
128
- s = (r == null ? void 0 : r.message) || (r == null ? void 0 : r.error) || s;
129
- } catch (r) {
139
+ const i = await e.json();
140
+ s = (i == null ? void 0 : i.message) || (i == null ? void 0 : i.error) || s;
141
+ } catch (i) {
130
142
  }
131
143
  throw new Error(`Deepspot SDK: ${s}`);
132
144
  }
@@ -134,7 +146,7 @@ class S {
134
146
  return (t == null ? void 0 : t.data) !== void 0 ? t.data : t;
135
147
  }
136
148
  }
137
- class w {
149
+ class E {
138
150
  constructor(e) {
139
151
  var t, s;
140
152
  this.destroyed = !1, this.refreshTimer = null, this.opts = e, this.filters = { ...e.activeFilters }, this.activePageId = (t = e.activePageId) != null ? t : "", this.activeTabId = (s = e.activeTabId) != null ? s : "";
@@ -151,6 +163,14 @@ class w {
151
163
  setFilters(e) {
152
164
  Object.assign(this.filters, e), this.scheduleRefresh();
153
165
  }
166
+ /** v2 alias for setFilter — sets a global filter and re-fetches data */
167
+ setGlobalFilter(e, t) {
168
+ this.setFilter(e, t);
169
+ }
170
+ /** v2: clear all active filters and re-fetch data */
171
+ clearFilters() {
172
+ this.filters = {}, this.scheduleRefresh();
173
+ }
154
174
  /** Navigate to a different page (dashboard embed only) */
155
175
  goToPage(e) {
156
176
  this.opts.embedType === "dashboard" && (this.activePageId = e, this.opts.renderer.goToPage(e));
@@ -183,10 +203,10 @@ class w {
183
203
  this.refreshTimer && clearTimeout(this.refreshTimer), this.refreshTimer = setTimeout(() => this.refresh(), 300);
184
204
  }
185
205
  async fetchData() {
186
- const { apiClient: e, dashboardId: t, componentId: s, token: r, embedType: i, embedLevel: a } = this.opts;
187
- return i === "report" && s ? e.getReportRender(t, s, r, {
206
+ const { apiClient: e, dashboardId: t, componentId: s, token: i, embedType: r, embedLevel: a } = this.opts;
207
+ return r === "report" && s ? e.getReportRender(t, s, i, {
188
208
  filters: this.filters
189
- }) : e.getDashboardRender(t, r, {
209
+ }) : e.getDashboardRender(t, i, {
190
210
  embedLevel: a,
191
211
  pageId: this.activePageId || void 0,
192
212
  tabId: this.activeTabId || void 0,
@@ -194,8 +214,8 @@ class w {
194
214
  });
195
215
  }
196
216
  }
197
- const K = 24, $ = 10, C = 12;
198
- class E {
217
+ const be = 24, M = 10, O = 12;
218
+ class ae {
199
219
  /**
200
220
  * @param containerWidth Actual pixel width of the grid container.
201
221
  * @param minY Minimum y value across all components (normalises
@@ -206,23 +226,23 @@ class E {
206
226
  }
207
227
  /** Pixel width of one column unit */
208
228
  get colWidth() {
209
- return this.containerWidth / K;
229
+ return this.containerWidth / be;
210
230
  }
211
231
  /** Convert grid position {x,y,w,h} → CSS absolute pixel values */
212
232
  toPx(e) {
213
- const t = this.colWidth, s = C / 2;
233
+ const t = this.colWidth, s = O / 2;
214
234
  return {
215
235
  left: e.x * t + s,
216
- top: (e.y - this.minY) * $ + s,
217
- width: e.w * t - C,
218
- height: e.h * $ - C
236
+ top: (e.y - this.minY) * M + s,
237
+ width: e.w * t - O,
238
+ height: e.h * M - O
219
239
  };
220
240
  }
221
241
  /** Total pixel height required to fit all positioned components */
222
242
  static totalHeight(e) {
223
243
  if (!e.length) return 400;
224
- const t = Math.min(...e.map((r) => r.y));
225
- return (Math.max(...e.map((r) => r.y + r.h)) - t) * $ + 40;
244
+ const t = Math.min(...e.map((i) => i.y));
245
+ return (Math.max(...e.map((i) => i.y + i.h)) - t) * M + 40;
226
246
  }
227
247
  /** Apply absolute positioning styles directly to a DOM element */
228
248
  applyStyles(e, t) {
@@ -230,21 +250,21 @@ class E {
230
250
  e.style.position = "absolute", e.style.left = `${s.left}px`, e.style.top = `${s.top}px`, e.style.width = `${s.width}px`, e.style.height = `${s.height}px`;
231
251
  }
232
252
  }
233
- let R = null;
234
- function q() {
235
- return R || (R = import("./apexcharts.common-k3hLWpB8.js").then((u) => u.a)), R;
253
+ let N = null;
254
+ function fe() {
255
+ return N || (N = import("./apexcharts.common-k3hLWpB8.js").then((w) => w.a)), N;
236
256
  }
237
- class O {
257
+ class ne {
238
258
  constructor(e) {
239
259
  this.chart = null, this.container = e;
240
260
  }
241
- async render(e, t, s, r) {
261
+ async render(e, t, s, i) {
242
262
  if (!t || t.length === 0) {
243
263
  this.renderEmpty(e.title);
244
264
  return;
245
265
  }
246
- const i = this.buildOptions(e, t, s, r);
247
- if (!i) {
266
+ const r = this.buildOptions(e, t, s, i);
267
+ if (!r) {
248
268
  this.renderEmpty(e.title);
249
269
  return;
250
270
  }
@@ -258,10 +278,10 @@ class O {
258
278
  if (a)
259
279
  try {
260
280
  this.chart && this.chart.destroy();
261
- const { default: d } = await q();
262
- this.chart = new d(a, i), this.chart.render();
263
- } catch (d) {
264
- console.error("[Deepspot SDK] ChartRenderer error:", d), a.innerHTML = '<div class="ds-chart-empty">Chart render error</div>';
281
+ const { default: o } = await fe();
282
+ this.chart = new o(a, r), this.chart.render();
283
+ } catch (o) {
284
+ console.error("[Deepspot SDK] ChartRenderer error:", o), a.innerHTML = '<div class="ds-chart-empty">Chart render error</div>';
265
285
  }
266
286
  }
267
287
  async update(e, t, s) {
@@ -269,11 +289,11 @@ class O {
269
289
  await this.render(e, t, s);
270
290
  return;
271
291
  }
272
- const { series: r, categories: i } = this.extractSeriesAndCategories(e, t);
292
+ const { series: i, categories: r } = this.extractSeriesAndCategories(e, t);
273
293
  try {
274
294
  this.chart.updateOptions({
275
- series: r,
276
- xaxis: { categories: i },
295
+ series: i,
296
+ xaxis: { categories: r },
277
297
  theme: { mode: s }
278
298
  });
279
299
  } catch (a) {
@@ -289,13 +309,13 @@ class O {
289
309
  this.chart = null;
290
310
  }
291
311
  // ── Private ─────────────────────────────────────────────────────────────────
292
- buildOptions(e, t, s, r) {
293
- const i = e.type;
294
- return i === "pie" || i === "donut" ? this.buildPieOptions(e, t, s, r) : i === "bar" || i === "line" || i === "area" ? this.buildCartesianOptions(e, t, s, r) : null;
312
+ buildOptions(e, t, s, i) {
313
+ const r = e.type;
314
+ return r === "pie" || r === "donut" ? this.buildPieOptions(e, t, s, i) : r === "bar" || r === "line" || r === "area" ? this.buildCartesianOptions(e, t, s, i) : null;
295
315
  }
296
- buildCartesianOptions(e, t, s, r) {
297
- var l;
298
- const { series: i, categories: a, xAxisLabel: d, yAxisLabel: o } = this.extractSeriesAndCategories(e, t), n = e.properties || {}, b = n.colors ? Object.values(n.colors) : ["#6366f1", "#8b5cf6", "#ec4899", "#f59e0b", "#10b981", "#3b82f6"], h = s === "dark";
316
+ buildCartesianOptions(e, t, s, i) {
317
+ var n;
318
+ const { series: r, categories: a, xAxisLabel: o, yAxisLabel: l } = this.extractSeriesAndCategories(e, t), d = e.properties || {}, h = d.colors ? Object.values(d.colors) : ["#6366f1", "#8b5cf6", "#ec4899", "#f59e0b", "#10b981", "#3b82f6"], b = s === "dark";
299
319
  return {
300
320
  chart: {
301
321
  type: e.type === "area" ? "area" : e.type === "line" ? "line" : "bar",
@@ -305,32 +325,32 @@ class O {
305
325
  fontFamily: "inherit",
306
326
  // Explicit height prevents ApexCharts from guessing the flex-child height
307
327
  // at render time (which can read as 0 before the browser settles layout).
308
- height: r != null ? r : "100%"
328
+ height: i != null ? i : "100%"
309
329
  },
310
330
  theme: { mode: s },
311
- series: i,
331
+ series: r,
312
332
  xaxis: {
313
333
  categories: a,
314
- title: { text: d },
334
+ title: { text: o },
315
335
  labels: {
316
336
  rotate: a.length > 8 ? -45 : 0,
317
- style: { colors: h ? "#94a3b8" : "#6b7280", fontSize: "11px" }
337
+ style: { colors: b ? "#94a3b8" : "#6b7280", fontSize: "11px" }
318
338
  },
319
- axisBorder: { color: h ? "#334155" : "#e5e7eb" },
320
- axisTicks: { color: h ? "#334155" : "#e5e7eb" }
339
+ axisBorder: { color: b ? "#334155" : "#e5e7eb" },
340
+ axisTicks: { color: b ? "#334155" : "#e5e7eb" }
321
341
  },
322
342
  yaxis: {
323
- title: { text: o },
324
- labels: { style: { colors: h ? "#94a3b8" : "#6b7280", fontSize: "11px" } }
343
+ title: { text: l },
344
+ labels: { style: { colors: b ? "#94a3b8" : "#6b7280", fontSize: "11px" } }
325
345
  },
326
- colors: b,
346
+ colors: h,
327
347
  legend: {
328
- show: i.length > 1 || ((l = n.showLegend) != null ? l : !1),
348
+ show: r.length > 1 || ((n = d.showLegend) != null ? n : !1),
329
349
  position: "bottom",
330
- labels: { colors: h ? "#94a3b8" : "#6b7280" }
350
+ labels: { colors: b ? "#94a3b8" : "#6b7280" }
331
351
  },
332
352
  grid: {
333
- borderColor: h ? "#1e293b" : "#f3f4f6",
353
+ borderColor: b ? "#1e293b" : "#f3f4f6",
334
354
  strokeDashArray: 4,
335
355
  padding: {
336
356
  bottom: a.length > 8 ? 60 : 10
@@ -346,34 +366,34 @@ class O {
346
366
  plotOptions: {
347
367
  bar: {
348
368
  borderRadius: 4,
349
- distributed: i.length === 1
369
+ distributed: r.length === 1
350
370
  }
351
371
  }
352
372
  };
353
373
  }
354
- buildPieOptions(e, t, s, r) {
355
- const i = e.properties || {}, a = t.length > 0 ? Object.keys(t[0]) : [], d = a[0] || "label", o = a[1] || "value", n = t.map((c) => {
356
- var p;
357
- return String((p = c[d]) != null ? p : "");
358
- }), b = t.map((c) => Number(c[o]) || 0), h = s === "dark", l = i.colors ? Object.values(i.colors) : ["#6366f1", "#8b5cf6", "#ec4899", "#f59e0b", "#10b981", "#3b82f6"];
374
+ buildPieOptions(e, t, s, i) {
375
+ const r = e.properties || {}, a = t.length > 0 ? Object.keys(t[0]) : [], o = a[0] || "label", l = a[1] || "value", d = t.map((p) => {
376
+ var f;
377
+ return String((f = p[o]) != null ? f : "");
378
+ }), h = t.map((p) => Number(p[l]) || 0), b = s === "dark", n = r.colors ? Object.values(r.colors) : ["#6366f1", "#8b5cf6", "#ec4899", "#f59e0b", "#10b981", "#3b82f6"];
359
379
  return {
360
380
  chart: {
361
381
  type: e.type,
362
382
  toolbar: { show: !1 },
363
383
  background: "transparent",
364
384
  fontFamily: "inherit",
365
- height: r != null ? r : "100%"
385
+ height: i != null ? i : "100%"
366
386
  },
367
387
  theme: { mode: s },
368
- series: b,
369
- labels: n,
370
- colors: l,
388
+ series: h,
389
+ labels: d,
390
+ colors: n,
371
391
  legend: {
372
392
  position: "bottom",
373
- labels: { colors: h ? "#94a3b8" : "#6b7280" }
393
+ labels: { colors: b ? "#94a3b8" : "#6b7280" }
374
394
  },
375
395
  tooltip: { theme: s },
376
- dataLabels: { enabled: n.length <= 8 },
396
+ dataLabels: { enabled: d.length <= 8 },
377
397
  plotOptions: {
378
398
  pie: {
379
399
  donut: { size: e.type === "donut" ? "65%" : "0%" }
@@ -382,38 +402,38 @@ class O {
382
402
  };
383
403
  }
384
404
  extractSeriesAndCategories(e, t) {
385
- const s = e.properties || {}, r = t.length > 0 ? Object.keys(t[0]) : [], i = s.xAxis || r[0] || "x";
405
+ const s = e.properties || {}, i = t.length > 0 ? Object.keys(t[0]) : [], r = s.xAxis || i[0] || "x";
386
406
  let a = [];
387
407
  if (s.selectedYAxisColumn)
388
408
  try {
389
- const l = typeof s.selectedYAxisColumn == "string" ? JSON.parse(s.selectedYAxisColumn) : s.selectedYAxisColumn;
390
- Array.isArray(l) && (a = l.map(
391
- (c) => typeof c == "string" ? { column: c } : c
409
+ const n = typeof s.selectedYAxisColumn == "string" ? JSON.parse(s.selectedYAxisColumn) : s.selectedYAxisColumn;
410
+ Array.isArray(n) && (a = n.map(
411
+ (p) => typeof p == "string" ? { column: p } : p
392
412
  ));
393
- } catch (l) {
413
+ } catch (n) {
394
414
  }
395
415
  if (!a.length && s.yAxis) {
396
- const l = s.yAxis;
397
- a = (Array.isArray(l) ? l : [l]).map((p) => ({ column: String(p) }));
416
+ const n = s.yAxis;
417
+ a = (Array.isArray(n) ? n : [n]).map((f) => ({ column: String(f) }));
398
418
  }
399
- !a.length && r.length > 1 && (a = r.slice(1).map((l) => ({ column: l })));
400
- const d = t.map((l) => {
401
- var c;
402
- return String((c = l[i]) != null ? c : "");
403
- }), o = t.length > 0 ? Object.keys(t[0]) : [], n = a.map((l) => {
404
- const c = o.includes(l.column) ? l.column : null, p = c ? null : o.find((f) => f.includes(l.column) || l.column.includes(f)), g = !c && !p ? o.find((f) => {
405
- var y;
406
- return f !== i && !isNaN(Number((y = t[0]) == null ? void 0 : y[f]));
407
- }) : null, m = c || p || g || l.column;
419
+ !a.length && i.length > 1 && (a = i.slice(1).map((n) => ({ column: n })));
420
+ const o = t.map((n) => {
421
+ var p;
422
+ return String((p = n[r]) != null ? p : "");
423
+ }), l = t.length > 0 ? Object.keys(t[0]) : [], d = a.map((n) => {
424
+ const p = l.includes(n.column) ? n.column : null, f = p ? null : l.find((u) => u.includes(n.column) || n.column.includes(u)), m = !p && !f ? l.find((u) => {
425
+ var g;
426
+ return u !== r && !isNaN(Number((g = t[0]) == null ? void 0 : g[u]));
427
+ }) : null, c = p || f || m || n.column;
408
428
  return {
409
- name: l.label || l.column.replace(/_/g, " "),
410
- data: t.map((f) => {
411
- const y = f[m];
412
- return y != null ? Number(y) : null;
429
+ name: n.label || n.column.replace(/_/g, " "),
430
+ data: t.map((u) => {
431
+ const g = u[c];
432
+ return g != null ? Number(g) : null;
413
433
  })
414
434
  };
415
- }), b = s.xAxisLabel || i.replace(/_/g, " "), h = s.yAxisLabel || (n.length === 1 ? n[0].name : "Values");
416
- return { series: n, categories: d, xAxisLabel: b, yAxisLabel: h };
435
+ }), h = s.xAxisLabel || r.replace(/_/g, " "), b = s.yAxisLabel || (d.length === 1 ? d[0].name : "Values");
436
+ return { series: d, categories: o, xAxisLabel: h, yAxisLabel: b };
417
437
  }
418
438
  renderEmpty(e) {
419
439
  this.container.innerHTML = `
@@ -424,34 +444,126 @@ class O {
424
444
  `;
425
445
  }
426
446
  }
427
- class j {
428
- render(e, t, s) {
429
- var n;
430
- if (!s || s.length === 0) {
447
+ class le {
448
+ constructor() {
449
+ this.columns = [], this.allData = [], this.currentRows = [], this.totalRows = 0, this.currentPage = 1, this.currentPageSize = 10, this.searchTerm = "", this.isLoading = !1;
450
+ }
451
+ // ── Public API ─────────────────────────────────────────────────────────────
452
+ render(e, t, s, i) {
453
+ var h;
454
+ this.container = e, this.component = t, this.fetchPage = i, this.searchTerm = "", this.currentPage = 1, this.currentPageSize = 10;
455
+ const r = s && !Array.isArray(s) && "rows" in s;
456
+ if (r) {
457
+ const b = s;
458
+ this.currentRows = b.rows, this.allData = [], this.totalRows = b.total, this.currentPage = b.page, this.currentPageSize = b.pageSize;
459
+ } else
460
+ this.allData = s || [], this.currentRows = [], this.totalRows = this.allData.length, this.currentPage = 1;
461
+ if (r && s.rows.length === 0 && s.total === 0 || !r && this.allData.length === 0) {
431
462
  e.innerHTML = `
432
463
  <div class="ds-table-card">
433
- <div class="ds-table-title">${t.title || ""}</div>
464
+ <div class="ds-table-header-row">
465
+ <span class="ds-table-dot"></span>
466
+ <div class="ds-table-title">${this.escape(t.title || "")}</div>
467
+ </div>
434
468
  <div class="ds-chart-empty">No data available</div>
435
469
  </div>
436
470
  `;
437
471
  return;
438
472
  }
439
- const r = Object.keys(s[0]), i = ((n = t.properties) == null ? void 0 : n.columns) || [], a = i.length ? i.filter((b) => r.includes(b)) : r, d = a.map((b) => `<th>${this.formatHeader(b)}</th>`).join(""), o = s.map((b) => `<tr>${a.map((l) => {
440
- const c = b[l];
441
- return `<td title="${this.escape(String(c != null ? c : ""))}">${this.escape(this.formatValue(c))}</td>`;
442
- }).join("")}</tr>`).join("");
443
- e.innerHTML = `
473
+ const a = r ? s.rows[0] : this.allData[0], o = a ? Object.keys(a) : [], l = ((h = t.properties) == null ? void 0 : h.columns) || [], d = l.length ? l.filter((b) => o.includes(b)) : [];
474
+ this.columns = d.length ? d : o, this.paint();
475
+ }
476
+ // ── Rendering ──────────────────────────────────────────────────────────────
477
+ paint() {
478
+ const { rows: e, startNum: t } = this.getPageRows(), s = Math.max(1, Math.ceil(this.totalRows / this.currentPageSize)), i = (this.currentPage - 1) * this.currentPageSize + 1, r = this.fetchPage ? Math.min(i - 1 + (this.isLoading ? this.currentPageSize : e.length), this.totalRows) : Math.min(this.currentPage * this.currentPageSize, this.totalRows), a = this.columns.map((n) => `<th>${this.escape(this.formatHeader(n))}</th>`).join(""), o = e.length === 0 ? `<tr><td colspan="${this.columns.length + 1}" style="text-align:center;padding:20px;color:#9ca3af">No results found</td></tr>` : e.map((n, p) => {
479
+ const f = this.columns.map((m) => {
480
+ const c = n[m];
481
+ return `<td title="${this.escape(String(c != null ? c : ""))}">${this.escape(this.formatValue(c))}</td>`;
482
+ }).join("");
483
+ return `<tr><td class="ds-table-sno">${t + p}</td>${f}</tr>`;
484
+ }).join(""), l = this.currentPageSize, d = [10, 25, 50, 100].map((n) => `<option value="${n}"${n === l ? " selected" : ""}>${n}</option>`).join(""), h = this.currentPage <= 1, b = this.currentPage >= s;
485
+ this.container.innerHTML = `
444
486
  <div class="ds-table-card">
445
- <div class="ds-table-title">${t.title || ""}</div>
487
+ <div class="ds-table-header-row">
488
+ <div class="ds-table-title-wrap">
489
+ <span class="ds-table-dot"></span>
490
+ <span class="ds-table-title">${this.escape(this.component.title || "")}</span>
491
+ </div>
492
+ </div>
446
493
  <div class="ds-table-scroll">
447
494
  <table class="ds-table">
448
- <thead><tr>${d}</tr></thead>
495
+ <thead><tr><th class="ds-table-sno-th">S.No</th>${a}</tr></thead>
449
496
  <tbody>${o}</tbody>
450
497
  </table>
451
498
  </div>
499
+ <div class="ds-table-footer">
500
+ <div class="ds-table-info">
501
+ <span>${i.toLocaleString()}–${r.toLocaleString()} of ${this.totalRows.toLocaleString()}</span>
502
+ <span class="ds-table-rows-label">Rows:</span>
503
+ <select class="ds-table-page-size">${d}</select>
504
+ </div>
505
+ <div class="ds-table-pagination">
506
+ <button class="ds-table-pg-btn" data-action="first" ${h ? "disabled" : ""}>&#171;</button>
507
+ <button class="ds-table-pg-btn" data-action="prev" ${h ? "disabled" : ""}>Previous</button>
508
+ <span class="ds-table-pg-info">Page ${this.currentPage} of ${s}</span>
509
+ <button class="ds-table-pg-btn" data-action="next" ${b ? "disabled" : ""}>Next</button>
510
+ <button class="ds-table-pg-btn" data-action="last" ${b ? "disabled" : ""}>&#187;</button>
511
+ </div>
512
+ </div>
513
+ ${this.isLoading ? '<div class="ds-table-loading-overlay"><div class="ds-embed-spinner"></div></div>' : ""}
452
514
  </div>
453
- `;
515
+ `, this.attachEvents();
516
+ }
517
+ attachEvents() {
518
+ const e = this.container.querySelector(".ds-table-search");
519
+ e == null || e.addEventListener("input", () => {
520
+ this.searchTerm = e.value, this.currentPage = 1, this.fetchPage || (this.totalRows = this.filteredRows().length, this.paint());
521
+ });
522
+ const t = this.container.querySelector(".ds-table-page-size");
523
+ t == null || t.addEventListener("change", () => {
524
+ this.currentPageSize = parseInt(t.value, 10), this.currentPage = 1, this.fetchPage ? this.loadPage(1) : (this.totalRows = this.filteredRows().length, this.paint());
525
+ }), this.container.querySelectorAll("[data-action]").forEach((s) => {
526
+ s.addEventListener("click", () => {
527
+ if (s.disabled) return;
528
+ const i = Math.max(1, Math.ceil(this.totalRows / this.currentPageSize)), r = s.dataset.action;
529
+ let a = this.currentPage;
530
+ r === "first" ? a = 1 : r === "prev" ? a = Math.max(1, this.currentPage - 1) : r === "next" ? a = Math.min(i, this.currentPage + 1) : r === "last" && (a = i), (a !== this.currentPage || r === "first" || r === "last") && (this.currentPage = a, this.fetchPage ? this.loadPage(a) : this.paint());
531
+ });
532
+ });
533
+ }
534
+ // ── Server-side page load ──────────────────────────────────────────────────
535
+ async loadPage(e) {
536
+ if (this.fetchPage) {
537
+ this.isLoading = !0, this.currentPage = e, this.paint();
538
+ try {
539
+ const t = await this.fetchPage(e, this.currentPageSize);
540
+ this.currentRows = t.rows || [], this.totalRows = Number(t.total) || this.currentRows.length, this.currentPage = Number(t.page) || e;
541
+ } catch (t) {
542
+ console.error("[Deepspot SDK] TableRenderer: page fetch failed", t);
543
+ } finally {
544
+ this.isLoading = !1, this.paint();
545
+ }
546
+ }
454
547
  }
548
+ // ── Data helpers ───────────────────────────────────────────────────────────
549
+ getPageRows() {
550
+ const e = (this.currentPage - 1) * this.currentPageSize + 1;
551
+ if (this.fetchPage)
552
+ return { rows: this.currentRows, startNum: e };
553
+ const t = this.filteredRows(), s = (this.currentPage - 1) * this.currentPageSize;
554
+ return { rows: t.slice(s, s + this.currentPageSize), startNum: e };
555
+ }
556
+ filteredRows() {
557
+ if (!this.searchTerm) return this.allData;
558
+ const e = this.searchTerm.toLowerCase();
559
+ return this.allData.filter(
560
+ (t) => this.columns.some((s) => {
561
+ var i;
562
+ return String((i = t[s]) != null ? i : "").toLowerCase().includes(e);
563
+ })
564
+ );
565
+ }
566
+ // ── Formatters ─────────────────────────────────────────────────────────────
455
567
  formatHeader(e) {
456
568
  return e.replace(/_/g, " ").replace(/\b\w/g, (t) => t.toUpperCase());
457
569
  }
@@ -462,26 +574,26 @@ class j {
462
574
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
463
575
  }
464
576
  }
465
- class M {
577
+ class ce {
466
578
  render(e, t, s) {
467
- const r = t.properties || {};
468
- let i = null;
579
+ const i = t.properties || {};
580
+ let r = null;
469
581
  if (s && s.length > 0) {
470
- const c = s[0], p = r.metric || Object.keys(c)[0], g = c[p];
471
- if (g !== void 0)
472
- i = g;
582
+ const f = s[0], m = i.metric || Object.keys(f)[0], c = f[m];
583
+ if (c !== void 0)
584
+ r = c;
473
585
  else {
474
- const m = Object.keys(c).find(
475
- (f) => f.includes(p) || p.includes(f)
586
+ const u = Object.keys(f).find(
587
+ (g) => g.includes(m) || m.includes(g)
476
588
  );
477
- i = c[m != null ? m : Object.keys(c)[0]];
589
+ r = f[u != null ? u : Object.keys(f)[0]];
478
590
  }
479
591
  }
480
- const a = this.formatValue(i, r), d = r.backgroundColor || "", o = r.textColor || "", n = t.title || "", b = d ? `background:${d};border-color:${d};` : "", h = o ? `color:${o};` : "", l = o ? `color:${o};opacity:0.7;` : "";
592
+ const a = this.formatValue(r, i), o = i.styleConfig || {}, l = o.backgroundColor || i.backgroundColor || "", d = o.color || o.textColor || i.textColor || "", h = t.title || "", b = l ? `background:${l};border-color:${l};` : "", n = d ? `color:${d};` : "", p = d ? `color:${d};opacity:0.7;` : "";
481
593
  e.innerHTML = `
482
594
  <div class="ds-card"${b ? ` style="${b}"` : ""}>
483
- <div class="ds-card-label"${l ? ` style="${l}"` : ""}>${n}</div>
484
- <div class="ds-card-value"${h ? ` style="${h}"` : ""}>${a}</div>
595
+ <div class="ds-card-label"${p ? ` style="${p}"` : ""}>${h}</div>
596
+ <div class="ds-card-value"${n ? ` style="${n}"` : ""}>${a}</div>
485
597
  </div>
486
598
  `;
487
599
  }
@@ -489,12 +601,12 @@ class M {
489
601
  if (e == null) return "—";
490
602
  const s = Number(e);
491
603
  if (isNaN(s)) return String(e);
492
- const r = (t == null ? void 0 : t.prefix) || (t == null ? void 0 : t.currencySymbol) || "", i = (t == null ? void 0 : t.suffix) || "";
604
+ const i = (t == null ? void 0 : t.prefix) || (t == null ? void 0 : t.currencySymbol) || "", r = (t == null ? void 0 : t.suffix) || "";
493
605
  let a;
494
- return Math.abs(s) >= 1e6 ? a = (s / 1e6).toFixed(1) + "M" : Math.abs(s) >= 1e3 ? a = (s / 1e3).toFixed(1) + "K" : a = s % 1 === 0 ? s.toLocaleString() : s.toFixed(2), `${r}${a}${i}`;
606
+ return Math.abs(s) >= 1e6 ? a = (s / 1e6).toFixed(1) + "M" : Math.abs(s) >= 1e3 ? a = (s / 1e3).toFixed(1) + "K" : a = s % 1 === 0 ? s.toLocaleString() : s.toFixed(2), `${i}${a}${r}`;
495
607
  }
496
608
  }
497
- class z {
609
+ class pe {
498
610
  constructor(e, t) {
499
611
  this.currentValues = {}, this.container = e, this.onFilterChange = t;
500
612
  }
@@ -514,31 +626,31 @@ class z {
514
626
  `select[data-filter-id="${e}"]`
515
627
  );
516
628
  if (!s) return;
517
- const r = s.value;
629
+ const i = s.value;
518
630
  s.innerHTML = '<option value="">All</option>' + t.map(
519
- (i) => `<option value="${this.escAttr(i)}">${this.escText(i)}</option>`
520
- ).join(""), r && t.includes(r) && (s.value = r);
631
+ (r) => `<option value="${this.escAttr(r)}">${this.escText(r)}</option>`
632
+ ).join(""), i && t.includes(i) && (s.value = i);
521
633
  }
522
634
  /** Update the stored values without re-rendering (for programmatic setFilter) */
523
635
  updateValues(e) {
524
636
  Object.assign(this.currentValues, e), Object.entries(e).forEach(([t, s]) => {
525
- const r = this.container.querySelector(`[data-filter-id="${t}"]`);
526
- r && s !== void 0 && (r.value = String(s));
637
+ const i = this.container.querySelector(`[data-filter-id="${t}"]`);
638
+ i && s !== void 0 && (i.value = String(s));
527
639
  });
528
640
  }
529
641
  // ── Private ─────────────────────────────────────────────────────────────────
530
642
  renderFilter(e, t) {
531
- const s = `ds-filter-${e.filterId}`, r = `<label class="ds-filter-label" for="${s}">${e.label}</label>`;
643
+ const s = `ds-filter-${e.filterId}`, i = `<label class="ds-filter-label" for="${s}">${e.label}</label>`;
532
644
  switch (e.type) {
533
645
  case "dropdown":
534
646
  return `
535
647
  <div class="ds-filter-item">
536
- ${r}
648
+ ${i}
537
649
  <select class="ds-filter-select" id="${s}" data-filter-id="${e.filterId}">
538
650
  <option value="">All</option>
539
- ${(e.options || []).map((d) => `
540
- <option value="${this.escAttr(d)}" ${t === d ? "selected" : ""}>
541
- ${this.escText(d)}
651
+ ${(e.options || []).map((o) => `
652
+ <option value="${this.escAttr(o)}" ${t === o ? "selected" : ""}>
653
+ ${this.escText(o)}
542
654
  </option>
543
655
  `).join("")}
544
656
  </select>
@@ -546,22 +658,22 @@ class z {
546
658
  case "multi-select":
547
659
  return `
548
660
  <div class="ds-filter-item">
549
- ${r}
661
+ ${i}
550
662
  <select class="ds-filter-select" id="${s}" data-filter-id="${e.filterId}" multiple size="1">
551
- ${(e.options || []).map((d) => `
552
- <option value="${this.escAttr(d)}">${this.escText(d)}</option>
663
+ ${(e.options || []).map((o) => `
664
+ <option value="${this.escAttr(o)}">${this.escText(o)}</option>
553
665
  `).join("")}
554
666
  </select>
555
667
  </div>`;
556
668
  case "date-range":
557
- const i = (t == null ? void 0 : t.from) || "", a = (t == null ? void 0 : t.to) || "";
669
+ const r = (t == null ? void 0 : t.from) || "", a = (t == null ? void 0 : t.to) || "";
558
670
  return `
559
671
  <div class="ds-filter-item">
560
- ${r}
672
+ ${i}
561
673
  <div class="ds-date-range-inputs">
562
674
  <input type="date" class="ds-filter-input"
563
675
  data-filter-id="${e.filterId}" data-date-part="from"
564
- value="${i}" />
676
+ value="${r}" />
565
677
  <span>–</span>
566
678
  <input type="date" class="ds-filter-input"
567
679
  data-filter-id="${e.filterId}" data-date-part="to"
@@ -571,7 +683,7 @@ class z {
571
683
  case "text-input":
572
684
  return `
573
685
  <div class="ds-filter-item">
574
- ${r}
686
+ ${i}
575
687
  <input type="text" class="ds-filter-input" id="${s}"
576
688
  data-filter-id="${e.filterId}"
577
689
  value="${this.escAttr(String(t != null ? t : ""))}"
@@ -580,7 +692,7 @@ class z {
580
692
  case "number-input":
581
693
  return `
582
694
  <div class="ds-filter-item">
583
- ${r}
695
+ ${i}
584
696
  <input type="number" class="ds-filter-input" id="${s}"
585
697
  data-filter-id="${e.filterId}"
586
698
  value="${this.escAttr(String(t != null ? t : ""))}" />
@@ -592,33 +704,33 @@ class z {
592
704
  attachListeners(e) {
593
705
  const t = {};
594
706
  this.container.querySelectorAll("[data-filter-id]").forEach((s) => {
595
- const r = s.dataset.filterId, i = s.dataset.datePart, a = e.find((o) => o.filterId === r), d = () => {
596
- let o;
597
- if ((a == null ? void 0 : a.type) === "date-range" && i)
598
- t[r] = t[r] || {}, t[r][i] = s.value, o = { ...t[r] };
707
+ const i = s.dataset.filterId, r = s.dataset.datePart, a = e.find((l) => l.filterId === i), o = () => {
708
+ let l;
709
+ if ((a == null ? void 0 : a.type) === "date-range" && r)
710
+ t[i] = t[i] || {}, t[i][r] = s.value, l = { ...t[i] };
599
711
  else if ((a == null ? void 0 : a.type) === "multi-select") {
600
- const n = s;
601
- o = Array.from(n.selectedOptions).map((b) => b.value).filter(Boolean);
712
+ const d = s;
713
+ l = Array.from(d.selectedOptions).map((h) => h.value).filter(Boolean);
602
714
  } else
603
- o = s.value;
604
- this.currentValues[r] = o, this.onFilterChange(r, o);
715
+ l = s.value;
716
+ this.currentValues[i] = l, this.onFilterChange(i, l);
605
717
  };
606
718
  s.addEventListener(
607
719
  (a == null ? void 0 : a.type) === "text-input" ? "input" : "change",
608
- d
720
+ o
609
721
  );
610
722
  });
611
723
  }
612
724
  escAttr(e) {
613
- return e.replace(/"/g, "&quot;").replace(/'/g, "&#39;");
725
+ return String(e != null ? e : "").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
614
726
  }
615
727
  escText(e) {
616
- return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
728
+ return String(e != null ? e : "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
617
729
  }
618
730
  }
619
- class N {
731
+ const H = class H {
620
732
  constructor(e, t) {
621
- this.activePageId = "", this.activeTabId = "", this.activeFilters = {}, this.chartRenderers = /* @__PURE__ */ new Map(), this.tableRenderer = new j(), this.cardRenderer = new M(), this.isLoadingTab = !1, this.root = e, this.opts = t, this.activeFilters = { ...t.initialFilters };
733
+ this.activePageId = "", this.activeTabId = "", this.activeFilters = {}, this.chartRenderers = /* @__PURE__ */ new Map(), this.tableRenderer = new le(), this.cardRenderer = new ce(), this.isLoadingTab = !1, this.root = e, this.opts = t, this.activeFilters = { ...t.initialFilters };
622
734
  }
623
735
  // ── Initial full render ───────────────────────────────────────────────────
624
736
  render(e) {
@@ -640,29 +752,62 @@ class N {
640
752
  this.chartRenderers.forEach((e) => e.destroy()), this.chartRenderers.clear(), this.root.innerHTML = "";
641
753
  }
642
754
  exportPDF() {
643
- const e = this.root.querySelector("#ds-canvas");
644
- e && import("./html2canvas.esm-CzwMv54K.js").then(
645
- ({ default: t }) => t(e, { scale: 2, useCORS: !0 }).then(
646
- (s) => import("./jspdf.es.min-d9hlG26J.js").then((r) => r.j).then(({ jsPDF: r }) => {
647
- const i = new r({ orientation: "landscape", unit: "px" });
648
- i.addImage(s.toDataURL("image/png"), "PNG", 0, 0, i.internal.pageSize.width, 0), i.save(`${this.renderData.dashboard.name || "dashboard"}.pdf`);
649
- })
650
- )
755
+ var n, p;
756
+ const e = this.root.querySelector("#ds-grid");
757
+ if (!e) return;
758
+ const t = this.root.style.height, s = this.root.style.overflow;
759
+ this.root.style.height = "auto", this.root.style.overflow = "visible";
760
+ const i = this.root.querySelector("#ds-canvas"), r = (n = i == null ? void 0 : i.style.height) != null ? n : "", a = (p = i == null ? void 0 : i.style.overflow) != null ? p : "";
761
+ i && (i.style.height = "auto", i.style.overflow = "visible");
762
+ const o = Array.from(e.querySelectorAll(".ds-table-scroll")), l = o.map((f) => ({
763
+ el: f,
764
+ overflow: f.style.overflow,
765
+ maxHeight: f.style.maxHeight,
766
+ height: f.style.height
767
+ }));
768
+ o.forEach((f) => {
769
+ f.style.overflow = "visible", f.style.maxHeight = "none", f.style.height = "auto";
770
+ });
771
+ const d = e.offsetWidth, h = parseInt(e.style.height, 10) || e.offsetHeight, b = e.getBoundingClientRect().top + window.scrollY;
772
+ import("./html2canvas.esm-CzwMv54K.js").then(
773
+ ({ default: f }) => f(e, {
774
+ scale: 2,
775
+ useCORS: !0,
776
+ allowTaint: !0,
777
+ logging: !1,
778
+ width: d,
779
+ height: h,
780
+ windowWidth: d,
781
+ windowHeight: h,
782
+ scrollX: 0,
783
+ scrollY: -b
784
+ }).then((m) => {
785
+ this.root.style.height = t, this.root.style.overflow = s, i && (i.style.height = r, i.style.overflow = a), l.forEach(({ el: c, overflow: u, maxHeight: g, height: k }) => {
786
+ c.style.overflow = u, c.style.maxHeight = g, c.style.height = k;
787
+ }), import("./jspdf.es.min-d9hlG26J.js").then((c) => c.j).then(({ jsPDF: c }) => {
788
+ const u = m.width / 2, g = m.height / 2, k = new c({
789
+ orientation: u >= g ? "landscape" : "portrait",
790
+ unit: "px",
791
+ format: [u, g]
792
+ });
793
+ k.addImage(m.toDataURL("image/png"), "PNG", 0, 0, u, g), k.save(`${this.renderData.dashboard.name || "dashboard"}.pdf`);
794
+ });
795
+ })
651
796
  );
652
797
  }
653
798
  exportCSV() {
654
799
  this.renderData.components.forEach((e) => {
655
800
  const t = this.renderData.data[e.id];
656
801
  if (!(t != null && t.length) || !["table", "bar", "line", "area"].includes(e.type)) return;
657
- const s = Object.keys(t[0]), r = [s.join(","), ...t.map(
658
- (a) => s.map((d) => {
659
- var o;
660
- return JSON.stringify((o = a[d]) != null ? o : "");
802
+ const s = Object.keys(t[0]), i = [s.join(","), ...t.map(
803
+ (a) => s.map((o) => {
804
+ var l;
805
+ return JSON.stringify((l = a[o]) != null ? l : "");
661
806
  }).join(",")
662
807
  )].join(`
663
808
  `);
664
809
  Object.assign(document.createElement("a"), {
665
- href: URL.createObjectURL(new Blob([r], { type: "text/csv" })),
810
+ href: URL.createObjectURL(new Blob([i], { type: "text/csv" })),
666
811
  download: `${e.title || e.id}.csv`
667
812
  }).click();
668
813
  });
@@ -673,11 +818,11 @@ class N {
673
818
  }
674
819
  // ── Shell ─────────────────────────────────────────────────────────────────
675
820
  buildShell() {
676
- const e = this.opts.embedLevel, t = this.renderData.dashboard.pages, s = e === "dashboard" && t.length > 1, r = e === "page" || e === "dashboard";
821
+ const e = this.opts.embedLevel, t = this.renderData.dashboard.pages, s = e === "dashboard" && t.length > 1, i = e === "page" || e === "dashboard";
677
822
  this.root.innerHTML = `
678
823
  ${this.opts.hideExport ? "" : '<div class="ds-toolbar" id="ds-toolbar"></div>'}
679
824
  ${s ? '<nav class="ds-page-nav" id="ds-page-nav"></nav>' : ""}
680
- ${r ? '<nav class="ds-page-nav" id="ds-tab-nav"></nav>' : ""}
825
+ ${i ? '<nav class="ds-page-nav" id="ds-tab-nav"></nav>' : ""}
681
826
  <div id="ds-filter-container"></div>
682
827
  <div class="ds-canvas" id="ds-canvas">
683
828
  <div class="ds-grid" id="ds-grid"></div>
@@ -687,11 +832,13 @@ class N {
687
832
  <div class="ds-embed-spinner"></div>
688
833
  </div>
689
834
  `, this.root.style.position = "relative", this.opts.hideExport || this.buildExportToolbar();
690
- const i = this.root.querySelector("#ds-filter-container");
691
- this.filterRenderer = new z(i, (a, d) => {
692
- var b, h;
693
- const o = this.renderData.filters.find((l) => l.filterId === a), n = (o == null ? void 0 : o.applyToField) || a;
694
- this.activeFilters[n] = d, (h = (b = this.opts).onFilterChange) == null || h.call(b, this.activeFilters), this.opts.onTabSwitch(this.activePageId, this.activeTabId);
835
+ const r = this.root.querySelector("#ds-filter-container");
836
+ this.filterRenderer = new pe(r, (a, o) => {
837
+ var b, n, p, f, m;
838
+ const l = (b = this.renderData.filters) == null ? void 0 : b.find((c) => c.filterId === a), d = (n = this.renderData.components) == null ? void 0 : n.find(
839
+ (c) => c.type === "inline-filter" && c.id === a
840
+ ), h = (l == null ? void 0 : l.applyToField) || ((p = d == null ? void 0 : d.properties) == null ? void 0 : p.applyToField) || a;
841
+ this.activeFilters[h] = o, (m = (f = this.opts).onFilterChange) == null || m.call(f, this.activeFilters), this.opts.onTabSwitch(this.activePageId, this.activeTabId);
695
842
  });
696
843
  }
697
844
  buildExportToolbar() {
@@ -699,7 +846,7 @@ class N {
699
846
  const e = this.root.querySelector("#ds-toolbar");
700
847
  e && (e.innerHTML = `
701
848
  <button class="ds-toolbar-btn" id="ds-btn-pdf">⬇ PDF</button>
702
- <button class="ds-toolbar-btn" id="ds-btn-csv">⬇ CSV</button>
849
+ <button class="ds-toolbar-btn" id="ds-btn-csv" style="display:none">⬇ CSV</button>
703
850
  `, (t = e.querySelector("#ds-btn-pdf")) == null || t.addEventListener("click", () => this.exportPDF()), (s = e.querySelector("#ds-btn-csv")) == null || s.addEventListener("click", () => this.exportCSV()));
704
851
  }
705
852
  // ── Navigation ────────────────────────────────────────────────────────────
@@ -713,9 +860,9 @@ class N {
713
860
  data-page-id="${t.pageId}">${t.title}</button>
714
861
  `).join(""), e.querySelectorAll(".ds-page-tab").forEach((t) => {
715
862
  t.addEventListener("click", () => {
716
- var r, i;
863
+ var i, r;
717
864
  const s = t.dataset.pageId;
718
- s === this.activePageId && !this.isLoadingTab || this.triggerTabSwitch(s, (i = (r = this.getTabsForPage(s)[0]) == null ? void 0 : r.id) != null ? i : "");
865
+ s === this.activePageId && !this.isLoadingTab || this.triggerTabSwitch(s, (r = (i = this.getTabsForPage(s)[0]) == null ? void 0 : i.id) != null ? r : "");
719
866
  });
720
867
  }));
721
868
  }
@@ -729,17 +876,16 @@ class N {
729
876
  e.style.display = "none";
730
877
  return;
731
878
  }
732
- e.style.display = "", e.innerHTML = s.map((r) => `
733
- <button class="ds-page-tab ${r.id === this.activeTabId ? "ds-active" : ""}"
734
- data-tab-id="${r.id}" data-page-id="${t}">${r.title}</button>
735
- `).join(""), e.querySelectorAll(".ds-page-tab").forEach((r) => {
736
- r.addEventListener("click", () => {
737
- const i = r.dataset.tabId, a = r.dataset.pageId;
738
- i === this.activeTabId && a === this.activePageId && !this.isLoadingTab || this.triggerTabSwitch(a, i);
879
+ e.style.display = "", e.innerHTML = s.map((i) => `
880
+ <button class="ds-page-tab ${i.id === this.activeTabId ? "ds-active" : ""}"
881
+ data-tab-id="${i.id}" data-page-id="${t}">${i.title}</button>
882
+ `).join(""), e.querySelectorAll(".ds-page-tab").forEach((i) => {
883
+ i.addEventListener("click", () => {
884
+ const r = i.dataset.tabId, a = i.dataset.pageId;
885
+ r === this.activeTabId && a === this.activePageId && !this.isLoadingTab || this.triggerTabSwitch(a, r);
739
886
  });
740
887
  });
741
888
  }
742
- /** Optimistically highlight new tab + show spinner, then fire callback */
743
889
  triggerTabSwitch(e, t) {
744
890
  this.isLoadingTab || !e || !t || (this.isLoadingTab = !0, this.activePageId = e, this.activeTabId = t, this.syncNavHighlight(), this.showTabSpinner(), this.opts.onTabSwitch(e, t));
745
891
  }
@@ -750,18 +896,42 @@ class N {
750
896
  const e = this.root.querySelector("#ds-tab-nav");
751
897
  e && this.buildTabButtons(e, this.activePageId);
752
898
  }
753
- // ── Filter bar ────────────────────────────────────────────────────────────
899
+ // ── Global Filter bar ─────────────────────────────────────────────────────
900
+ // Merges global filters (from renderData.filters[]) with inline-filter
901
+ // components (type='inline-filter' in renderData.components[]).
902
+ // Inline-filter components are NOT rendered in the grid — they appear here.
754
903
  renderFilterBar() {
755
- this.opts.hideFilters || (this.filterRenderer.render(this.renderData.filters, this.activeFilters), this.fetchFilterOptions());
904
+ if (this.opts.hideGlobalFilters) return;
905
+ const e = [
906
+ ...this.renderData.filters || [],
907
+ ...this.inlineFiltersAsDefinitions()
908
+ ];
909
+ this.filterRenderer.render(e, this.activeFilters), this.fetchFilterOptions();
756
910
  }
757
911
  updateFilterBar() {
758
- this.opts.hideFilters || (this.filterRenderer.render(this.renderData.filters, this.activeFilters), this.fetchFilterOptions());
912
+ if (this.opts.hideGlobalFilters) return;
913
+ const e = [
914
+ ...this.renderData.filters || [],
915
+ ...this.inlineFiltersAsDefinitions()
916
+ ];
917
+ this.filterRenderer.render(e, this.activeFilters), this.fetchFilterOptions();
918
+ }
919
+ /** Convert inline-filter ComponentConfig entries to FilterDefinition shape */
920
+ inlineFiltersAsDefinitions() {
921
+ return this.opts.hideInlineFilters ? [] : (this.renderData.components || []).filter((e) => e.type === "inline-filter").map((e) => {
922
+ var t, s, i, r, a, o, l, d;
923
+ return {
924
+ filterId: e.id,
925
+ label: ((t = e.properties) == null ? void 0 : t.filterLabel) || e.title || "",
926
+ type: ((s = e.properties) == null ? void 0 : s.filterType) || "dropdown",
927
+ options: ((i = e.properties) == null ? void 0 : i.filterOptions) || ((r = e.properties) == null ? void 0 : r.options) || [],
928
+ defaultValue: (a = e.properties) == null ? void 0 : a.defaultValue,
929
+ targetComponents: ((o = e.properties) == null ? void 0 : o.targetComponents) || [],
930
+ filterOperator: (l = e.properties) == null ? void 0 : l.filterOperator,
931
+ applyToField: ((d = e.properties) == null ? void 0 : d.applyToField) || e.id
932
+ };
933
+ });
759
934
  }
760
- /**
761
- * For every dropdown / multi-select filter whose options array is empty,
762
- * call onFetchFilterOptions(filterId) and populate the select element.
763
- * Mirrors: GET /dashboard-builder/{dashboardId}/filters/{filterId}/options
764
- */
765
935
  async fetchFilterOptions() {
766
936
  if (this.opts.onFetchFilterOptions)
767
937
  for (const e of this.renderData.filters) {
@@ -775,45 +945,124 @@ class N {
775
945
  this.hideTabSpinner();
776
946
  const e = this.root.querySelector("#ds-grid");
777
947
  if (!e) return;
778
- this.chartRenderers.forEach((n) => n.destroy()), this.chartRenderers.clear();
779
- const t = this.renderData.components;
948
+ if (!this.opts.hideBackground) {
949
+ const d = this.root.querySelector("#ds-canvas"), h = this.renderData.dashboard.pages.find(
950
+ (n) => n.pageId === this.activePageId
951
+ ), b = (h == null ? void 0 : h.backgroundColor) || "";
952
+ d && (d.style.background = b), this.root.style.background = b;
953
+ }
954
+ this.chartRenderers.forEach((d) => d.destroy()), this.chartRenderers.clear();
955
+ const t = (this.renderData.components || []).filter(
956
+ (d) => d.type !== "inline-filter"
957
+ );
780
958
  if (!t.length) {
781
959
  e.style.height = "200px", e.innerHTML = '<div class="ds-chart-empty" style="padding-top:80px;">No components on this tab.</div>';
782
960
  return;
783
961
  }
784
- const s = e.clientWidth || this.root.clientWidth || 800, r = t.map((n) => n.position), i = r.length ? Math.min(...r.map((n) => n.y)) : 0, a = new E(s, i);
785
- e.style.height = `${E.totalHeight(r)}px`, e.innerHTML = "";
786
- const d = 36, o = [];
787
- t.forEach((n) => {
788
- const b = document.createElement("div");
789
- b.className = "ds-component-wrapper", b.dataset.componentId = n.id, a.applyStyles(b, n.position), e.appendChild(b);
790
- const h = a.toPx(n.position), l = Math.max(50, h.height - d);
791
- o.push(this.renderComponent(b, n, l));
792
- }), Promise.all(o).catch(() => {
962
+ const s = e.clientWidth || this.root.clientWidth || 800, i = t.map((d) => d.position), r = i.length ? Math.min(...i.map((d) => d.y)) : 0, a = new ae(s, r);
963
+ e.style.height = `${ae.totalHeight(i)}px`, e.innerHTML = "";
964
+ const o = 36, l = [];
965
+ t.forEach((d) => {
966
+ var p, f, m;
967
+ const h = document.createElement("div");
968
+ if (h.className = "ds-component-wrapper", h.dataset.componentId = d.id, a.applyStyles(h, d.position), !this.opts.hideBackground) {
969
+ const c = ((f = (p = d.properties) == null ? void 0 : p.styleConfig) == null ? void 0 : f.backgroundColor) || ((m = d.properties) == null ? void 0 : m.backgroundColor);
970
+ c && (h.style.background = c);
971
+ }
972
+ e.appendChild(h);
973
+ const b = a.toPx(d.position), n = Math.max(50, b.height - o);
974
+ l.push(
975
+ this.renderComponent(h, d, n).catch((c) => {
976
+ console.error(`[Deepspot SDK] Failed to render component ${d.id} (${d.type}):`, c), h.innerHTML = `<div style="padding:8px;color:#ef4444;font-size:12px;">⚠ ${d.type} render error</div>`;
977
+ })
978
+ );
979
+ }), Promise.all(l).catch(() => {
793
980
  });
794
981
  }
982
+ // ── Component renderer switch ─────────────────────────────────────────────
795
983
  async renderComponent(e, t, s) {
796
- var a, d;
797
- const r = this.renderData.data[t.id] || [], i = this.opts.theme;
984
+ var a, o, l, d, h, b, n, p, f, m, c, u, g, k, T, C, $, R, I, P, L, U, W, _, Y, J, X, Z, Q, V, ee, te, se, ie, re;
985
+ const i = this.renderData.data[t.id] || [], r = this.opts.theme;
798
986
  switch (t.type) {
799
987
  case "bar":
800
988
  case "line":
801
989
  case "pie":
802
990
  case "donut":
803
- case "area": {
804
- const o = new O(e);
805
- await o.render(t, r, i, s), this.chartRenderers.set(t.id, o);
991
+ case "area":
992
+ case "scatter":
993
+ case "stacked-bar": {
994
+ const v = new ne(e);
995
+ await v.render(t, i, r, s), this.chartRenderers.set(t.id, v);
806
996
  break;
807
997
  }
808
- case "table":
809
- this.tableRenderer.render(e, t, r);
998
+ case "table": {
999
+ const v = this.opts.onFetchTablePage ? (x, S) => this.opts.onFetchTablePage(t.id, x, S) : void 0;
1000
+ this.tableRenderer.render(e, t, i, v);
810
1001
  break;
1002
+ }
811
1003
  case "number-card":
812
- this.cardRenderer.render(e, t, r);
1004
+ this.cardRenderer.render(e, t, i);
1005
+ break;
1006
+ case "text-heading": {
1007
+ if (this.opts.hideText) break;
1008
+ const v = ((o = (a = t.properties) == null ? void 0 : a.data) == null ? void 0 : o.dataContent) || ((l = t.properties) == null ? void 0 : l.content) || t.title || "", x = ((d = t.properties) == null ? void 0 : d.styleConfig) || {}, S = this.scToInlineStyle(x), y = this.opts.hideBackground ? {} : this.parseTwColor((b = (h = t.properties) == null ? void 0 : h.color) != null ? b : ""), F = [[
1009
+ y.bg ? `background:${y.bg}` : "",
1010
+ y.text ? `color:${y.text}` : ""
1011
+ ].filter(Boolean).join(";"), S].filter(Boolean).join(";");
1012
+ e.innerHTML = `<div class="ds-text-heading" style="${F}">${v}</div>`;
1013
+ break;
1014
+ }
1015
+ case "text-subheading": {
1016
+ if (this.opts.hideText) break;
1017
+ const v = ((p = (n = t.properties) == null ? void 0 : n.data) == null ? void 0 : p.dataContent) || ((f = t.properties) == null ? void 0 : f.content) || t.title || "", x = ((m = t.properties) == null ? void 0 : m.styleConfig) || {}, S = this.scToInlineStyle(x), y = this.opts.hideBackground ? {} : this.parseTwColor((u = (c = t.properties) == null ? void 0 : c.color) != null ? u : ""), F = [[
1018
+ y.bg ? `background:${y.bg}` : "",
1019
+ y.text ? `color:${y.text}` : ""
1020
+ ].filter(Boolean).join(";"), S].filter(Boolean).join(";");
1021
+ e.innerHTML = `<div class="ds-text-subheading" style="${F}">${v}</div>`;
1022
+ break;
1023
+ }
1024
+ case "text-body": {
1025
+ if (this.opts.hideText) break;
1026
+ const v = ((k = (g = t.properties) == null ? void 0 : g.data) == null ? void 0 : k.dataContent) || ((T = t.properties) == null ? void 0 : T.content) || "", x = ((C = t.properties) == null ? void 0 : C.styleConfig) || {}, S = this.scToInlineStyle(x), y = this.opts.hideBackground ? {} : this.parseTwColor((R = ($ = t.properties) == null ? void 0 : $.color) != null ? R : ""), F = [[
1027
+ y.bg ? `background:${y.bg}` : "",
1028
+ y.text ? `color:${y.text}` : ""
1029
+ ].filter(Boolean).join(";"), S].filter(Boolean).join(";");
1030
+ e.innerHTML = `<div class="ds-text-body" style="${F}">${v}</div>`;
1031
+ break;
1032
+ }
1033
+ case "text-box": {
1034
+ if (this.opts.hideText) break;
1035
+ const v = ((P = (I = t.properties) == null ? void 0 : I.data) == null ? void 0 : P.dataContent) || ((L = t.properties) == null ? void 0 : L.content) || "", x = ((U = t.properties) == null ? void 0 : U.styleConfig) || {}, S = this.scToInlineStyle(x), y = this.opts.hideBackground ? {} : this.parseTwColor((_ = (W = t.properties) == null ? void 0 : W.color) != null ? _ : ""), F = [[
1036
+ y.bg ? `background:${y.bg}` : "",
1037
+ y.text ? `color:${y.text}` : ""
1038
+ ].filter(Boolean).join(";"), S].filter(Boolean).join(";");
1039
+ e.innerHTML = `<div class="ds-text-box" style="${F}">${v}</div>`;
813
1040
  break;
1041
+ }
814
1042
  case "text": {
815
- const o = Object.entries(((a = t.properties) == null ? void 0 : a.style) || {}).map(([n, b]) => `${n}:${b}`).join(";");
816
- e.innerHTML = `<div style="${o};padding:8px;">${((d = t.properties) == null ? void 0 : d.content) || ""}</div>`;
1043
+ if (this.opts.hideText) break;
1044
+ const v = ((J = (Y = t.properties) == null ? void 0 : Y.data) == null ? void 0 : J.dataContent) || ((X = t.properties) == null ? void 0 : X.content) || "", x = ((Z = t.properties) == null ? void 0 : Z.styleConfig) || {}, S = this.scToInlineStyle(x), y = this.opts.hideBackground ? {} : this.parseTwColor((V = (Q = t.properties) == null ? void 0 : Q.color) != null ? V : ""), F = [[
1045
+ y.bg ? `background:${y.bg}` : "",
1046
+ y.text ? `color:${y.text}` : ""
1047
+ ].filter(Boolean).join(";"), S].filter(Boolean).join(";");
1048
+ e.innerHTML = `<div class="ds-text-body" style="${F}">${v}</div>`;
1049
+ break;
1050
+ }
1051
+ case "header": {
1052
+ if (this.opts.hideHeader) break;
1053
+ const v = ((te = (ee = t.properties) == null ? void 0 : ee.data) == null ? void 0 : te.dataContent) || ((se = t.properties) == null ? void 0 : se.content) || t.title || "", x = ((ie = t.properties) == null ? void 0 : ie.styleConfig) || {}, S = !this.opts.hideBackground && x.backgroundColor ? `background:${x.backgroundColor};` : "", y = x.color ? `color:${x.color};` : x.textColor ? `color:${x.textColor};` : "";
1054
+ e.innerHTML = `
1055
+ <div class="ds-header-component" style="${S}${y}">
1056
+ <div class="ds-header-content">${v}</div>
1057
+ </div>`;
1058
+ break;
1059
+ }
1060
+ case "section": {
1061
+ const v = ((re = t.properties) == null ? void 0 : re.styleConfig) || {}, x = !this.opts.hideBackground && v.backgroundColor ? `background:${v.backgroundColor};` : "";
1062
+ e.innerHTML = `
1063
+ <div class="ds-section-wrapper" style="${x}">
1064
+ ${t.title ? `<div class="ds-section-title">${t.title}</div>` : ""}
1065
+ </div>`;
817
1066
  break;
818
1067
  }
819
1068
  }
@@ -828,14 +1077,86 @@ class N {
828
1077
  e && (e.style.display = "none"), t && (t.style.opacity = "1");
829
1078
  }
830
1079
  // ── Helpers ───────────────────────────────────────────────────────────────
1080
+ /**
1081
+ * Convert a styleConfig object to an inline CSS string.
1082
+ * Maps camelCase keys (e.g. fontSize) to kebab-case CSS properties.
1083
+ * Skips backgroundColor — that is applied to the wrapper div separately
1084
+ * (so it can support CSS gradients via `background` shorthand).
1085
+ */
1086
+ scToInlineStyle(e) {
1087
+ const t = /* @__PURE__ */ new Set(["backgroundColor"]), s = (i) => i.replace(/([A-Z])/g, "-$1").toLowerCase();
1088
+ return Object.entries(e).filter(([i, r]) => !t.has(i) && r != null && r !== "").map(([i, r]) => `${s(i)}:${r}`).join(";");
1089
+ }
1090
+ /**
1091
+ * Parse a Tailwind utility class string (e.g. "bg-violet-100 text-violet-600")
1092
+ * into plain CSS hex values. Used for text components whose builder color
1093
+ * is stored as Tailwind class names rather than raw CSS.
1094
+ */
1095
+ parseTwColor(e) {
1096
+ if (!e) return {};
1097
+ const t = {};
1098
+ for (const s of e.split(/\s+/)) {
1099
+ if (!s) continue;
1100
+ if (s === "bg-white") {
1101
+ t.bg = "#ffffff";
1102
+ continue;
1103
+ }
1104
+ if (s === "bg-black") {
1105
+ t.bg = "#000000";
1106
+ continue;
1107
+ }
1108
+ if (s === "bg-transparent") {
1109
+ t.bg = "transparent";
1110
+ continue;
1111
+ }
1112
+ if (s === "text-white") {
1113
+ t.text = "#ffffff";
1114
+ continue;
1115
+ }
1116
+ if (s === "text-black") {
1117
+ t.text = "#000000";
1118
+ continue;
1119
+ }
1120
+ const i = /^(bg|text)-([a-z]+)-(\d+)$/.exec(s);
1121
+ if (!i) continue;
1122
+ const r = H.TW_PALETTE[i[2]], a = r == null ? void 0 : r[Number(i[3])];
1123
+ a && (i[1] === "bg" && (t.bg = a), i[1] === "text" && (t.text = a));
1124
+ }
1125
+ return t;
1126
+ }
831
1127
  getTabsForPage(e) {
832
1128
  var t, s;
833
- return (s = (t = this.renderData.dashboard.pages.find((r) => r.pageId === e)) == null ? void 0 : t.tabs) != null ? s : [];
1129
+ return (s = (t = this.renderData.dashboard.pages.find((i) => i.pageId === e)) == null ? void 0 : t.tabs) != null ? s : [];
834
1130
  }
835
- }
836
- class H {
1131
+ };
1132
+ H.TW_PALETTE = {
1133
+ slate: { 50: "#f8fafc", 100: "#f1f5f9", 200: "#e2e8f0", 300: "#cbd5e1", 400: "#94a3b8", 500: "#64748b", 600: "#475569", 700: "#334155", 800: "#1e293b", 900: "#0f172a" },
1134
+ gray: { 50: "#f9fafb", 100: "#f3f4f6", 200: "#e5e7eb", 300: "#d1d5db", 400: "#9ca3af", 500: "#6b7280", 600: "#4b5563", 700: "#374151", 800: "#1f2937", 900: "#111827" },
1135
+ zinc: { 50: "#fafafa", 100: "#f4f4f5", 200: "#e4e4e7", 300: "#d4d4d8", 400: "#a1a1aa", 500: "#71717a", 600: "#52525b", 700: "#3f3f46", 800: "#27272a", 900: "#18181b" },
1136
+ neutral: { 50: "#fafafa", 100: "#f5f5f5", 200: "#e5e5e5", 300: "#d4d4d4", 400: "#a3a3a3", 500: "#737373", 600: "#525252", 700: "#404040", 800: "#262626", 900: "#171717" },
1137
+ stone: { 50: "#fafaf9", 100: "#f5f5f4", 200: "#e7e5e4", 300: "#d6d3d1", 400: "#a8a29e", 500: "#78716c", 600: "#57534e", 700: "#44403c", 800: "#292524", 900: "#1c1917" },
1138
+ red: { 50: "#fef2f2", 100: "#fee2e2", 200: "#fecaca", 300: "#fca5a5", 400: "#f87171", 500: "#ef4444", 600: "#dc2626", 700: "#b91c1c", 800: "#991b1b", 900: "#7f1d1d" },
1139
+ orange: { 50: "#fff7ed", 100: "#ffedd5", 200: "#fed7aa", 300: "#fdba74", 400: "#fb923c", 500: "#f97316", 600: "#ea580c", 700: "#c2410c", 800: "#9a3412", 900: "#7c2d12" },
1140
+ amber: { 50: "#fffbeb", 100: "#fef3c7", 200: "#fde68a", 300: "#fcd34d", 400: "#fbbf24", 500: "#f59e0b", 600: "#d97706", 700: "#b45309", 800: "#92400e", 900: "#78350f" },
1141
+ yellow: { 50: "#fefce8", 100: "#fef9c3", 200: "#fef08a", 300: "#fde047", 400: "#facc15", 500: "#eab308", 600: "#ca8a04", 700: "#a16207", 800: "#854d0e", 900: "#713f12" },
1142
+ lime: { 50: "#f7fee7", 100: "#ecfccb", 200: "#d9f99d", 300: "#bef264", 400: "#a3e635", 500: "#84cc16", 600: "#65a30d", 700: "#4d7c0f", 800: "#3f6212", 900: "#365314" },
1143
+ green: { 50: "#f0fdf4", 100: "#dcfce7", 200: "#bbf7d0", 300: "#86efac", 400: "#4ade80", 500: "#22c55e", 600: "#16a34a", 700: "#15803d", 800: "#166534", 900: "#14532d" },
1144
+ emerald: { 50: "#ecfdf5", 100: "#d1fae5", 200: "#a7f3d0", 300: "#6ee7b7", 400: "#34d399", 500: "#10b981", 600: "#059669", 700: "#047857", 800: "#065f46", 900: "#064e3b" },
1145
+ teal: { 50: "#f0fdfa", 100: "#ccfbf1", 200: "#99f6e4", 300: "#5eead4", 400: "#2dd4bf", 500: "#14b8a6", 600: "#0d9488", 700: "#0f766e", 800: "#115e59", 900: "#134e4a" },
1146
+ cyan: { 50: "#ecfeff", 100: "#cffafe", 200: "#a5f3fc", 300: "#67e8f9", 400: "#22d3ee", 500: "#06b6d4", 600: "#0891b2", 700: "#0e7490", 800: "#155e75", 900: "#164e63" },
1147
+ sky: { 50: "#f0f9ff", 100: "#e0f2fe", 200: "#bae6fd", 300: "#7dd3fc", 400: "#38bdf8", 500: "#0ea5e9", 600: "#0284c7", 700: "#0369a1", 800: "#075985", 900: "#0c4a6e" },
1148
+ blue: { 50: "#eff6ff", 100: "#dbeafe", 200: "#bfdbfe", 300: "#93c5fd", 400: "#60a5fa", 500: "#3b82f6", 600: "#2563eb", 700: "#1d4ed8", 800: "#1e40af", 900: "#1e3a8a" },
1149
+ indigo: { 50: "#eef2ff", 100: "#e0e7ff", 200: "#c7d2fe", 300: "#a5b4fc", 400: "#818cf8", 500: "#6366f1", 600: "#4f46e5", 700: "#4338ca", 800: "#3730a3", 900: "#312e81" },
1150
+ violet: { 50: "#f5f3ff", 100: "#ede9fe", 200: "#ddd6fe", 300: "#c4b5fd", 400: "#a78bfa", 500: "#8b5cf6", 600: "#7c3aed", 700: "#6d28d9", 800: "#5b21b6", 900: "#4c1d95" },
1151
+ purple: { 50: "#faf5ff", 100: "#f3e8ff", 200: "#e9d5ff", 300: "#d8b4fe", 400: "#c084fc", 500: "#a855f7", 600: "#9333ea", 700: "#7e22ce", 800: "#6b21a8", 900: "#581c87" },
1152
+ fuchsia: { 50: "#fdf4ff", 100: "#fae8ff", 200: "#f5d0fe", 300: "#f0abfc", 400: "#e879f9", 500: "#d946ef", 600: "#c026d3", 700: "#a21caf", 800: "#86198f", 900: "#701a75" },
1153
+ pink: { 50: "#fdf2f8", 100: "#fce7f3", 200: "#fbcfe8", 300: "#f9a8d4", 400: "#f472b6", 500: "#ec4899", 600: "#db2777", 700: "#be185d", 800: "#9d174d", 900: "#831843" },
1154
+ rose: { 50: "#fff1f2", 100: "#ffe4e6", 200: "#fecdd3", 300: "#fda4af", 400: "#fb7185", 500: "#f43f5e", 600: "#e11d48", 700: "#be123c", 800: "#9f1239", 900: "#881337" }
1155
+ };
1156
+ let D = H;
1157
+ class he {
837
1158
  constructor(e, t) {
838
- this.chartRenderer = null, this.tableRenderer = new j(), this.cardRenderer = new M(), this.root = e, this.theme = t;
1159
+ this.chartRenderer = null, this.tableRenderer = new le(), this.cardRenderer = new ce(), this.root = e, this.theme = t;
839
1160
  }
840
1161
  render(e, t) {
841
1162
  const s = e.components[0];
@@ -846,8 +1167,8 @@ class H {
846
1167
  </div>`;
847
1168
  return;
848
1169
  }
849
- const r = e.data[s.id] || [];
850
- this.renderComponent(s, r), t == null || t();
1170
+ const i = e.data[s.id] || [];
1171
+ this.renderComponent(s, i), t == null || t();
851
1172
  }
852
1173
  update(e) {
853
1174
  const t = e.components[0];
@@ -881,7 +1202,7 @@ class H {
881
1202
  case "pie":
882
1203
  case "donut":
883
1204
  case "area":
884
- (s = this.chartRenderer) == null || s.destroy(), this.chartRenderer = new O(this.root), this.chartRenderer.render(e, t, this.theme);
1205
+ (s = this.chartRenderer) == null || s.destroy(), this.chartRenderer = new ne(this.root), this.chartRenderer.render(e, t, this.theme);
885
1206
  break;
886
1207
  case "table":
887
1208
  this.tableRenderer.render(this.root, e, t);
@@ -894,12 +1215,12 @@ class H {
894
1215
  }
895
1216
  }
896
1217
  }
897
- let D = !1;
898
- function F() {
899
- if (!(D || typeof document == "undefined")) {
900
- D = !0;
1218
+ let oe = !1;
1219
+ function q() {
1220
+ if (!(oe || typeof document == "undefined")) {
1221
+ oe = !0;
901
1222
  try {
902
- const u = `/* ─────────────────────────────────────────────────────────────────────────────
1223
+ const w = `/* ─────────────────────────────────────────────────────────────────────────────
903
1224
  Deepspot SDK — Base Embed Styles
904
1225
  Injected once into the host page's <head> by the SDK.
905
1226
  All selectors are scoped under .ds-embed-* to avoid leaking into host styles.
@@ -924,15 +1245,18 @@ function F() {
924
1245
  height: 100%;
925
1246
  overflow: auto;
926
1247
  position: relative;
1248
+ /* Default white background — overridden by page backgroundColor from publish page */
1249
+ background: #ffffff;
1250
+ color: #111827;
927
1251
  }
928
1252
 
929
1253
  .ds-embed-root.ds-theme-light {
930
- background: #ffffff;
1254
+ /* No forced background — let component styleConfig backgrounds show through */
931
1255
  color: #111827;
932
1256
  }
933
1257
 
934
1258
  .ds-embed-root.ds-theme-dark {
935
- background: #0f172a;
1259
+ /* No forced background — let component styleConfig backgrounds show through */
936
1260
  color: #f1f5f9;
937
1261
  }
938
1262
 
@@ -1182,6 +1506,7 @@ function F() {
1182
1506
  overflow: hidden;
1183
1507
  display: flex;
1184
1508
  flex-direction: column;
1509
+ position: relative;
1185
1510
  }
1186
1511
 
1187
1512
  .ds-theme-dark .ds-table-card {
@@ -1189,21 +1514,100 @@ function F() {
1189
1514
  border-color: #334155;
1190
1515
  }
1191
1516
 
1517
+ /* ── Table header: dot + title on left, search on right ──────────────────────*/
1518
+ .ds-table-header-row {
1519
+ display: flex;
1520
+ align-items: center;
1521
+ justify-content: space-between;
1522
+ padding: 10px 14px 8px;
1523
+ flex-shrink: 0;
1524
+ gap: 8px;
1525
+ border-bottom: 1px solid #f3f4f6;
1526
+ }
1527
+
1528
+ .ds-theme-dark .ds-table-header-row {
1529
+ border-bottom-color: #334155;
1530
+ }
1531
+
1532
+ .ds-table-title-wrap {
1533
+ display: flex;
1534
+ align-items: center;
1535
+ gap: 6px;
1536
+ min-width: 0;
1537
+ }
1538
+
1539
+ .ds-table-dot {
1540
+ width: 8px;
1541
+ height: 8px;
1542
+ border-radius: 50%;
1543
+ background: #6366f1;
1544
+ flex-shrink: 0;
1545
+ }
1546
+
1192
1547
  .ds-table-title {
1193
- padding: 10px 14px 4px;
1194
1548
  font-size: 13px;
1195
1549
  font-weight: 600;
1196
1550
  color: #374151;
1197
- flex-shrink: 0;
1551
+ white-space: nowrap;
1552
+ overflow: hidden;
1553
+ text-overflow: ellipsis;
1198
1554
  }
1199
1555
 
1200
1556
  .ds-theme-dark .ds-table-title {
1201
1557
  color: #e2e8f0;
1202
1558
  }
1203
1559
 
1560
+ /* ── Search ──────────────────────────────────────────────────────────────────*/
1561
+ .ds-table-search-wrap {
1562
+ position: relative;
1563
+ flex-shrink: 0;
1564
+ }
1565
+
1566
+ .ds-table-search-icon {
1567
+ position: absolute;
1568
+ left: 8px;
1569
+ top: 50%;
1570
+ transform: translateY(-50%);
1571
+ width: 14px;
1572
+ height: 14px;
1573
+ color: #9ca3af;
1574
+ pointer-events: none;
1575
+ }
1576
+
1577
+ .ds-table-search {
1578
+ height: 30px;
1579
+ padding: 0 10px 0 28px;
1580
+ border: 1px solid #e5e7eb;
1581
+ border-radius: 6px;
1582
+ font-size: 12px;
1583
+ background: #f9fafb;
1584
+ color: #374151;
1585
+ width: 180px;
1586
+ outline: none;
1587
+ transition: border-color 0.15s, box-shadow 0.15s;
1588
+ }
1589
+
1590
+ .ds-table-search:focus {
1591
+ border-color: #6366f1;
1592
+ box-shadow: 0 0 0 2px rgba(99,102,241,0.15);
1593
+ background: #fff;
1594
+ }
1595
+
1596
+ .ds-theme-dark .ds-table-search {
1597
+ background: #0f172a;
1598
+ border-color: #334155;
1599
+ color: #e2e8f0;
1600
+ }
1601
+
1602
+ .ds-theme-dark .ds-table-search:focus {
1603
+ background: #1e293b;
1604
+ }
1605
+
1606
+ /* ── Scroll area ─────────────────────────────────────────────────────────────*/
1204
1607
  .ds-table-scroll {
1205
1608
  flex: 1;
1206
1609
  overflow: auto;
1610
+ min-height: 0;
1207
1611
  }
1208
1612
 
1209
1613
  .ds-table {
@@ -1212,6 +1616,21 @@ function F() {
1212
1616
  font-size: 12px;
1213
1617
  }
1214
1618
 
1619
+ .ds-table-sno-th {
1620
+ width: 48px;
1621
+ text-align: center !important;
1622
+ }
1623
+
1624
+ .ds-table-sno {
1625
+ text-align: center;
1626
+ color: #9ca3af;
1627
+ font-size: 11px;
1628
+ }
1629
+
1630
+ .ds-theme-dark .ds-table-sno {
1631
+ color: #64748b;
1632
+ }
1633
+
1215
1634
  .ds-table th {
1216
1635
  position: sticky;
1217
1636
  top: 0;
@@ -1253,7 +1672,123 @@ function F() {
1253
1672
  }
1254
1673
 
1255
1674
  .ds-theme-dark .ds-table tr:hover td {
1675
+ background: #0f172a;
1676
+ }
1677
+
1678
+ /* ── Footer: info + pagination ───────────────────────────────────────────────*/
1679
+ .ds-table-footer {
1680
+ display: flex;
1681
+ align-items: center;
1682
+ justify-content: space-between;
1683
+ padding: 8px 14px;
1684
+ border-top: 1px solid #f3f4f6;
1685
+ flex-shrink: 0;
1686
+ gap: 8px;
1687
+ flex-wrap: wrap;
1688
+ }
1689
+
1690
+ .ds-theme-dark .ds-table-footer {
1691
+ border-top-color: #334155;
1692
+ }
1693
+
1694
+ .ds-table-info {
1695
+ display: flex;
1696
+ align-items: center;
1697
+ gap: 8px;
1698
+ font-size: 12px;
1699
+ color: #6b7280;
1700
+ }
1701
+
1702
+ .ds-theme-dark .ds-table-info {
1703
+ color: #94a3b8;
1704
+ }
1705
+
1706
+ .ds-table-rows-label {
1707
+ margin-left: 4px;
1708
+ }
1709
+
1710
+ .ds-table-page-size {
1711
+ height: 28px;
1712
+ padding: 0 6px;
1713
+ border: 1px solid #e5e7eb;
1714
+ border-radius: 5px;
1715
+ font-size: 12px;
1716
+ background: #fff;
1717
+ color: #374151;
1718
+ cursor: pointer;
1719
+ outline: none;
1720
+ }
1721
+
1722
+ .ds-theme-dark .ds-table-page-size {
1723
+ background: #0f172a;
1724
+ border-color: #334155;
1725
+ color: #e2e8f0;
1726
+ }
1727
+
1728
+ .ds-table-pagination {
1729
+ display: flex;
1730
+ align-items: center;
1731
+ gap: 6px;
1732
+ }
1733
+
1734
+ .ds-table-pg-btn {
1735
+ height: 28px;
1736
+ padding: 0 10px;
1737
+ border: 1px solid #e5e7eb;
1738
+ border-radius: 5px;
1739
+ font-size: 12px;
1740
+ font-weight: 500;
1741
+ background: #fff;
1742
+ color: #374151;
1743
+ cursor: pointer;
1744
+ transition: background 0.12s, border-color 0.12s;
1745
+ white-space: nowrap;
1746
+ }
1747
+
1748
+ .ds-table-pg-btn:hover:not(:disabled) {
1749
+ background: #f3f4f6;
1750
+ border-color: #d1d5db;
1751
+ }
1752
+
1753
+ .ds-table-pg-btn:disabled {
1754
+ opacity: 0.4;
1755
+ cursor: not-allowed;
1756
+ }
1757
+
1758
+ .ds-theme-dark .ds-table-pg-btn {
1256
1759
  background: #1e293b;
1760
+ border-color: #334155;
1761
+ color: #e2e8f0;
1762
+ }
1763
+
1764
+ .ds-theme-dark .ds-table-pg-btn:hover:not(:disabled) {
1765
+ background: #0f172a;
1766
+ }
1767
+
1768
+ .ds-table-pg-info {
1769
+ font-size: 12px;
1770
+ color: #6b7280;
1771
+ white-space: nowrap;
1772
+ }
1773
+
1774
+ .ds-theme-dark .ds-table-pg-info {
1775
+ color: #94a3b8;
1776
+ }
1777
+
1778
+ /* ── Loading overlay while fetching a page ───────────────────────────────────*/
1779
+ .ds-table-loading-overlay {
1780
+ position: absolute;
1781
+ inset: 0;
1782
+ background: rgba(255,255,255,0.6);
1783
+ display: flex;
1784
+ align-items: center;
1785
+ justify-content: center;
1786
+ border-radius: 10px;
1787
+ z-index: 10;
1788
+ }
1789
+
1790
+ .ds-theme-dark .ds-table-loading-overlay {
1791
+ background: rgba(30,41,59,0.7);
1257
1792
  }
1258
1793
 
1259
1794
  /* ── KPI Number Card ───────────────────────────────────────────────────────── */
@@ -1296,6 +1831,179 @@ function F() {
1296
1831
  color: #f1f5f9;
1297
1832
  }
1298
1833
 
1834
+ /* ── v2: Text / content components ────────────────────────────────────────── */
1835
+
1836
+ .ds-text-heading {
1837
+ width: 100%;
1838
+ height: 100%;
1839
+ display: flex;
1840
+ flex-direction: column;
1841
+ justify-content: center;
1842
+ padding: 8px 12px;
1843
+ font-size: 20px;
1844
+ font-weight: 700;
1845
+ color: #111827;
1846
+ line-height: 1.3;
1847
+ overflow: hidden;
1848
+ }
1849
+
1850
+ .ds-theme-dark .ds-text-heading {
1851
+ color: #f1f5f9;
1852
+ }
1853
+
1854
+ .ds-text-subheading {
1855
+ width: 100%;
1856
+ height: 100%;
1857
+ display: flex;
1858
+ flex-direction: column;
1859
+ justify-content: center;
1860
+ padding: 6px 12px;
1861
+ font-size: 15px;
1862
+ font-weight: 600;
1863
+ color: #374151;
1864
+ line-height: 1.4;
1865
+ overflow: hidden;
1866
+ }
1867
+
1868
+ .ds-theme-dark .ds-text-subheading {
1869
+ color: #cbd5e1;
1870
+ }
1871
+
1872
+ .ds-text-body {
1873
+ width: 100%;
1874
+ height: 100%;
1875
+ padding: 8px 12px;
1876
+ font-size: 14px;
1877
+ color: #374151;
1878
+ line-height: 1.6;
1879
+ overflow: auto;
1880
+ }
1881
+
1882
+ .ds-theme-dark .ds-text-body {
1883
+ color: #94a3b8;
1884
+ }
1885
+
1886
+ .ds-text-box {
1887
+ width: 100%;
1888
+ height: 100%;
1889
+ padding: 10px 14px;
1890
+ font-size: 13px;
1891
+ color: #374151;
1892
+ line-height: 1.6;
1893
+ border: 1px solid #e5e7eb;
1894
+ border-radius: 8px;
1895
+ background: #f9fafb;
1896
+ overflow: auto;
1897
+ }
1898
+
1899
+ .ds-theme-dark .ds-text-box {
1900
+ color: #cbd5e1;
1901
+ border-color: #334155;
1902
+ background: #1e293b;
1903
+ }
1904
+
1905
+ /* ── v2: Header component ──────────────────────────────────────────────────── */
1906
+
1907
+ .ds-header-component {
1908
+ width: 100%;
1909
+ height: 100%;
1910
+ display: flex;
1911
+ align-items: center;
1912
+ padding: 12px 20px;
1913
+ background: #f3f4f6;
1914
+ border-bottom: 1px solid #e5e7eb;
1915
+ overflow: hidden;
1916
+ }
1917
+
1918
+ .ds-theme-dark .ds-header-component {
1919
+ background: #1e293b;
1920
+ border-bottom-color: #334155;
1921
+ }
1922
+
1923
+ .ds-header-content {
1924
+ font-size: 18px;
1925
+ font-weight: 700;
1926
+ color: #111827;
1927
+ white-space: nowrap;
1928
+ overflow: hidden;
1929
+ text-overflow: ellipsis;
1930
+ }
1931
+
1932
+ .ds-theme-dark .ds-header-content {
1933
+ color: #f1f5f9;
1934
+ }
1935
+
1936
+ /* ── v2: Section container ─────────────────────────────────────────────────── */
1937
+
1938
+ .ds-section-wrapper {
1939
+ width: 100%;
1940
+ height: 100%;
1941
+ border: 1px solid #e5e7eb;
1942
+ border-radius: 10px;
1943
+ background: #f9fafb;
1944
+ overflow: hidden;
1945
+ }
1946
+
1947
+ .ds-theme-dark .ds-section-wrapper {
1948
+ border-color: #334155;
1949
+ background: #1e293b;
1950
+ }
1951
+
1952
+ .ds-section-title {
1953
+ padding: 8px 14px;
1954
+ font-size: 12px;
1955
+ font-weight: 600;
1956
+ text-transform: uppercase;
1957
+ letter-spacing: 0.05em;
1958
+ color: #6b7280;
1959
+ border-bottom: 1px solid #e5e7eb;
1960
+ }
1961
+
1962
+ .ds-theme-dark .ds-section-title {
1963
+ color: #94a3b8;
1964
+ border-bottom-color: #334155;
1965
+ }
1966
+
1967
+ /* ── v2: Inline filter (selection-filter placed in-grid) ───────────────────── */
1968
+
1969
+ .ds-inline-filter {
1970
+ width: 100%;
1971
+ height: 100%;
1972
+ display: flex;
1973
+ flex-direction: column;
1974
+ justify-content: center;
1975
+ gap: 4px;
1976
+ padding: 6px 10px;
1977
+ }
1978
+
1979
+ .ds-inline-filter-select,
1980
+ .ds-inline-filter-input {
1981
+ width: 100%;
1982
+ height: 34px;
1983
+ padding: 0 10px;
1984
+ border: 1px solid #d1d5db;
1985
+ border-radius: 6px;
1986
+ font-size: 13px;
1987
+ background: #ffffff;
1988
+ color: #111827;
1989
+ cursor: pointer;
1990
+ outline: none;
1991
+ transition: border-color 0.15s, box-shadow 0.15s;
1992
+ }
1993
+
1994
+ .ds-inline-filter-select:focus,
1995
+ .ds-inline-filter-input:focus {
1996
+ border-color: #6366f1;
1997
+ box-shadow: 0 0 0 2px rgba(99, 102, 241, 0.2);
1998
+ }
1999
+
2000
+ .ds-theme-dark .ds-inline-filter-select,
2001
+ .ds-theme-dark .ds-inline-filter-input {
2002
+ background: #1e293b;
2003
+ border-color: #334155;
2004
+ color: #f1f5f9;
2005
+ }
2006
+
1299
2007
  /* ── Export toolbar ────────────────────────────────────────────────────────── */
1300
2008
  .ds-toolbar {
1301
2009
  display: flex;
@@ -1335,42 +2043,42 @@ function F() {
1335
2043
  background: #0f172a;
1336
2044
  }
1337
2045
  `, e = document.createElement("style");
1338
- e.id = "deepspot-sdk-styles", e.textContent = u, document.head.appendChild(e);
1339
- } catch (u) {
2046
+ e.id = "deepspot-sdk-styles", e.textContent = w, document.head.appendChild(e);
2047
+ } catch (w) {
1340
2048
  }
1341
2049
  }
1342
2050
  }
1343
- function P(u) {
1344
- if (typeof u == "string") {
1345
- const e = document.querySelector(u);
1346
- if (!e) throw new Error(`Deepspot SDK: container "${u}" not found in DOM`);
2051
+ function de(w) {
2052
+ if (typeof w == "string") {
2053
+ const e = document.querySelector(w);
2054
+ if (!e) throw new Error(`Deepspot SDK: container "${w}" not found in DOM`);
1347
2055
  return e;
1348
2056
  }
1349
- return u;
2057
+ return w;
1350
2058
  }
1351
- class U {
2059
+ class ge {
1352
2060
  constructor(e) {
1353
2061
  if (!e.apiKey) throw new Error("Deepspot SDK: apiKey is required");
1354
2062
  if (!e.baseUrl) throw new Error("Deepspot SDK: baseUrl is required");
1355
- this.apiClient = new S(e.baseUrl, e.apiKey), F();
2063
+ this.apiClient = new K(e.baseUrl, e.apiKey), q();
1356
2064
  }
1357
2065
  // ── Embed full dashboard ────────────────────────────────────────────────────
1358
2066
  async embedDashboard(e) {
1359
- var a, d, o, n, b;
1360
- const t = P(e.container), s = (a = e.embedLevel) != null ? a : "dashboard", r = (d = e.theme) != null ? d : "light";
2067
+ var a, o, l, d, h, b, n, p, f, m;
2068
+ const t = de(e.container), s = (a = e.embedLevel) != null ? a : "dashboard", i = (o = e.theme) != null ? o : "light";
1361
2069
  t.style.height = e.height || "600px", t.style.display = "block";
1362
- const i = this.createRoot(t, r);
1363
- this.showLoading(i);
2070
+ const r = this.createRoot(t, i);
2071
+ this.showLoading(r);
1364
2072
  try {
1365
- const h = await this.apiClient.getEmbedToken({
2073
+ const c = await this.apiClient.getEmbedToken({
1366
2074
  dashboardId: e.dashboardId,
1367
2075
  embedType: "dashboard",
1368
2076
  embedLevel: s,
1369
2077
  userId: e.userId,
1370
2078
  tenantId: e.tenantId
1371
- }), l = await this.apiClient.getDashboardRender(
2079
+ }), u = await this.apiClient.getDashboardRender(
1372
2080
  e.dashboardId,
1373
- h,
2081
+ c,
1374
2082
  {
1375
2083
  embedLevel: s,
1376
2084
  pageId: e.pageId,
@@ -1378,61 +2086,69 @@ class U {
1378
2086
  filters: e.filters || {}
1379
2087
  }
1380
2088
  );
1381
- let c;
1382
- const p = new N(i, {
2089
+ let g;
2090
+ const k = new D(r, {
1383
2091
  embedLevel: s,
1384
- theme: r,
1385
- hideFilters: (o = e.hideFilters) != null ? o : !1,
1386
- hideExport: (n = e.hideExport) != null ? n : !1,
2092
+ theme: i,
2093
+ // v1 backward compat (hideFilters hideGlobalFilters)
2094
+ hideFilters: (l = e.hideGlobalFilters) != null ? l : !1,
2095
+ hideExport: (d = e.hideExport) != null ? d : !1,
2096
+ // v2 visibility
2097
+ hideGlobalFilters: (h = e.hideGlobalFilters) != null ? h : !1,
2098
+ hideInlineFilters: (b = e.hideInlineFilters) != null ? b : !1,
2099
+ hideText: (n = e.hideText) != null ? n : !1,
2100
+ hideHeader: (p = e.hideHeader) != null ? p : !1,
2101
+ hideBackground: (f = e.hideBackground) != null ? f : !1,
1387
2102
  initialFilters: e.filters || {},
1388
2103
  onFilterChange: e.onFilterChange,
1389
2104
  onReady: e.onReady,
1390
- onFetchFilterOptions: (g) => this.apiClient.getFilterOptions(e.dashboardId, g, h),
1391
- onTabSwitch: async (g, m) => {
1392
- var f, y, x;
1393
- (f = e.onTabSwitch) == null || f.call(e, g, m);
2105
+ onFetchFilterOptions: (T) => this.apiClient.getFilterOptions(e.dashboardId, T, c),
2106
+ onFetchTablePage: (T, C, $) => this.apiClient.getTablePage(e.dashboardId, T, C, $, c),
2107
+ onTabSwitch: async (T, C) => {
2108
+ var $, R, I;
2109
+ ($ = e.onTabSwitch) == null || $.call(e, T, C);
1394
2110
  try {
1395
- const v = await this.apiClient.getDashboardRender(
2111
+ const P = await this.apiClient.getDashboardRender(
1396
2112
  e.dashboardId,
1397
- h,
2113
+ c,
1398
2114
  {
1399
2115
  embedLevel: s,
1400
- pageId: g,
1401
- tabId: m,
1402
- filters: (x = (y = c == null ? void 0 : c.getActiveFilters()) != null ? y : e.filters) != null ? x : {}
2116
+ pageId: T,
2117
+ tabId: C,
2118
+ filters: (I = (R = g == null ? void 0 : g.getActiveFilters()) != null ? R : e.filters) != null ? I : {}
1403
2119
  }
1404
2120
  );
1405
- p.update(v);
1406
- } catch (v) {
1407
- console.error("Deepspot SDK: tab fetch failed", v);
2121
+ k.update(P);
2122
+ } catch (P) {
2123
+ console.error("Deepspot SDK: tab fetch failed", P);
1408
2124
  }
1409
2125
  }
1410
2126
  });
1411
- return p.render(l), c = new w({
2127
+ return k.render(u), g = new E({
1412
2128
  dashboardId: e.dashboardId,
1413
- token: h,
2129
+ token: c,
1414
2130
  embedType: "dashboard",
1415
2131
  embedLevel: s,
1416
- activePageId: l.activePage,
1417
- activeTabId: l.activeTab,
2132
+ activePageId: u.activePage,
2133
+ activeTabId: u.activeTab,
1418
2134
  activeFilters: e.filters || {},
1419
2135
  apiClient: this.apiClient,
1420
- renderer: p,
2136
+ renderer: k,
1421
2137
  onFilterChange: e.onFilterChange
1422
- }), c;
1423
- } catch (h) {
1424
- throw this.showError(i, (h == null ? void 0 : h.message) || "Failed to load dashboard"), (b = e.onError) == null || b.call(e, (h == null ? void 0 : h.message) || "Failed to load dashboard"), h;
2138
+ }), g;
2139
+ } catch (c) {
2140
+ throw this.showError(r, (c == null ? void 0 : c.message) || "Failed to load dashboard"), (m = e.onError) == null || m.call(e, (c == null ? void 0 : c.message) || "Failed to load dashboard"), c;
1425
2141
  }
1426
2142
  }
1427
2143
  // ── Embed single report (component) ────────────────────────────────────────
1428
2144
  async embedReport(e) {
1429
- var r;
1430
- const t = P(e.container);
2145
+ var i;
2146
+ const t = de(e.container);
1431
2147
  t.style.height = e.height || "400px", t.style.display = "block";
1432
2148
  const s = this.createRoot(t, e.theme || "light");
1433
2149
  this.showLoading(s);
1434
2150
  try {
1435
- const i = await this.apiClient.getEmbedToken({
2151
+ const r = await this.apiClient.getEmbedToken({
1436
2152
  dashboardId: e.dashboardId,
1437
2153
  embedType: "report",
1438
2154
  componentId: e.componentId,
@@ -1441,20 +2157,20 @@ class U {
1441
2157
  }), a = await this.apiClient.getReportRender(
1442
2158
  e.dashboardId,
1443
2159
  e.componentId,
1444
- i,
2160
+ r,
1445
2161
  { filters: e.filters || {} }
1446
- ), d = new H(s, e.theme || "light");
1447
- return d.render(a, e.onReady), new w({
2162
+ ), o = new he(s, e.theme || "light");
2163
+ return o.render(a, e.onReady), new E({
1448
2164
  dashboardId: e.dashboardId,
1449
2165
  componentId: e.componentId,
1450
- token: i,
2166
+ token: r,
1451
2167
  embedType: "report",
1452
2168
  activeFilters: e.filters || {},
1453
2169
  apiClient: this.apiClient,
1454
- renderer: d
2170
+ renderer: o
1455
2171
  });
1456
- } catch (i) {
1457
- throw this.showError(s, (i == null ? void 0 : i.message) || "Failed to load report"), (r = e.onError) == null || r.call(e, (i == null ? void 0 : i.message) || "Failed to load report"), i;
2172
+ } catch (r) {
2173
+ throw this.showError(s, (r == null ? void 0 : r.message) || "Failed to load report"), (i = e.onError) == null || i.call(e, (r == null ? void 0 : r.message) || "Failed to load report"), r;
1458
2174
  }
1459
2175
  }
1460
2176
  // ── Private helpers ─────────────────────────────────────────────────────────
@@ -1481,75 +2197,83 @@ class U {
1481
2197
  `;
1482
2198
  }
1483
2199
  }
1484
- const L = class L extends HTMLElement {
2200
+ const B = class B extends HTMLElement {
1485
2201
  constructor() {
1486
2202
  super(...arguments), this.instance = null, this.connected = !1;
1487
2203
  }
1488
2204
  connectedCallback() {
1489
- this.connected = !0, F(), this.style.display = "block", this.renderRoot = document.createElement("div"), this.renderRoot.className = "ds-embed-root", this.appendChild(this.renderRoot), this.mount();
2205
+ this.connected = !0, q(), this.style.display = "block", this.renderRoot = document.createElement("div"), this.renderRoot.className = "ds-embed-root", this.appendChild(this.renderRoot), this.mount();
1490
2206
  }
1491
2207
  disconnectedCallback() {
1492
2208
  var e;
1493
2209
  this.connected = !1, (e = this.instance) == null || e.destroy(), this.instance = null;
1494
2210
  }
1495
2211
  attributeChangedCallback(e, t, s) {
1496
- var r;
1497
- t === s || !this.connected || ((r = this.instance) == null || r.destroy(), this.instance = null, this.mount());
2212
+ var i;
2213
+ t === s || !this.connected || ((i = this.instance) == null || i.destroy(), this.instance = null, this.mount());
1498
2214
  }
1499
2215
  async mount() {
1500
- const e = this.getAttribute("dashboard-id"), t = this.getAttribute("api-key"), s = this.getAttribute("base-url") || "", r = this.getAttribute("user-id") || void 0, i = this.getAttribute("tenant-id") || void 0, a = this.getAttribute("embed-level") || "dashboard", d = this.getAttribute("theme") || "light", o = this.getAttribute("height") || "600px", n = this.getAttribute("page-id") || void 0, b = this.getAttribute("tab-id") || void 0, h = this.getAttribute("hide-filters") === "true", l = this.getAttribute("hide-export") === "true";
2216
+ const e = this.getAttribute("dashboard-id"), t = this.getAttribute("api-key"), s = this.getAttribute("base-url") || "", i = this.getAttribute("user-id") || void 0, r = this.getAttribute("tenant-id") || void 0, a = this.getAttribute("embed-level") || "dashboard", o = this.getAttribute("theme") || "light", l = this.getAttribute("height") || "600px", d = this.getAttribute("page-id") || void 0, h = this.getAttribute("tab-id") || void 0, b = this.getAttribute("hide-filters") === "true", n = this.getAttribute("hide-export") === "true", p = this.getAttribute("hide-global-filters") === "true" || b, f = this.getAttribute("hide-inline-filters") === "true", m = this.getAttribute("hide-text") === "true", c = this.getAttribute("hide-header") === "true", u = this.getAttribute("hide-background") === "true";
1501
2217
  if (!e || !t || !s) {
1502
2218
  this.showError("Missing required attributes: dashboard-id, api-key, base-url");
1503
2219
  return;
1504
2220
  }
1505
- this.renderRoot.style.height = o, this.renderRoot.className = `ds-embed-root ds-theme-${d}`, this.showLoading();
2221
+ this.renderRoot.style.height = l, this.renderRoot.className = `ds-embed-root ds-theme-${o}`, this.showLoading();
1506
2222
  try {
1507
- const c = new S(s, t), p = await c.getEmbedToken({
2223
+ const g = new K(s, t), k = await g.getEmbedToken({
1508
2224
  dashboardId: e,
1509
2225
  embedType: "dashboard",
1510
2226
  embedLevel: a,
1511
- userId: r,
1512
- tenantId: i
1513
- }), g = await c.getDashboardRender(e, p, {
2227
+ userId: i,
2228
+ tenantId: r
2229
+ }), T = await g.getDashboardRender(e, k, {
1514
2230
  embedLevel: a,
1515
- pageId: n,
1516
- tabId: b,
2231
+ pageId: d,
2232
+ tabId: h,
1517
2233
  filters: {}
1518
- }), m = new N(this.renderRoot, {
2234
+ }), C = new D(this.renderRoot, {
1519
2235
  embedLevel: a,
1520
- theme: d,
1521
- hideFilters: h,
1522
- hideExport: l,
2236
+ theme: o,
2237
+ // v1 backward compat
2238
+ hideFilters: p,
2239
+ hideExport: n,
2240
+ // v2 visibility
2241
+ hideGlobalFilters: p,
2242
+ hideInlineFilters: f,
2243
+ hideText: m,
2244
+ hideHeader: c,
2245
+ hideBackground: u,
1523
2246
  initialFilters: {},
1524
- onFetchFilterOptions: (f) => c.getFilterOptions(e, f, p),
1525
- onTabSwitch: async (f, y) => {
1526
- var x, v;
2247
+ onFetchFilterOptions: ($) => g.getFilterOptions(e, $, k),
2248
+ onFetchTablePage: ($, R, I) => g.getTablePage(e, $, R, I, k),
2249
+ onTabSwitch: async ($, R) => {
2250
+ var I, P;
1527
2251
  try {
1528
- const I = await c.getDashboardRender(e, p, {
2252
+ const L = await g.getDashboardRender(e, k, {
1529
2253
  embedLevel: a,
1530
- pageId: f,
1531
- tabId: y,
1532
- filters: (v = (x = this.instance) == null ? void 0 : x.getActiveFilters()) != null ? v : {}
2254
+ pageId: $,
2255
+ tabId: R,
2256
+ filters: (P = (I = this.instance) == null ? void 0 : I.getActiveFilters()) != null ? P : {}
1533
2257
  });
1534
- m.update(I);
1535
- } catch (I) {
1536
- console.error("Deepspot SDK: tab fetch failed", I);
2258
+ C.update(L);
2259
+ } catch (L) {
2260
+ console.error("Deepspot SDK: tab fetch failed", L);
1537
2261
  }
1538
2262
  }
1539
2263
  });
1540
- m.render(g), this.instance = new w({
2264
+ C.render(T), this.instance = new E({
1541
2265
  dashboardId: e,
1542
- token: p,
2266
+ token: k,
1543
2267
  embedLevel: a,
1544
2268
  embedType: "dashboard",
1545
- activePageId: g.activePage,
1546
- activeTabId: g.activeTab,
2269
+ activePageId: T.activePage,
2270
+ activeTabId: T.activeTab,
1547
2271
  activeFilters: {},
1548
- apiClient: c,
1549
- renderer: m
2272
+ apiClient: g,
2273
+ renderer: C
1550
2274
  });
1551
- } catch (c) {
1552
- this.showError((c == null ? void 0 : c.message) || "Failed to load dashboard");
2275
+ } catch (g) {
2276
+ this.showError((g == null ? void 0 : g.message) || "Failed to load dashboard");
1553
2277
  }
1554
2278
  }
1555
2279
  showLoading() {
@@ -1593,7 +2317,7 @@ const L = class L extends HTMLElement {
1593
2317
  (e = this.instance) == null || e.exportPDF();
1594
2318
  }
1595
2319
  };
1596
- L.observedAttributes = [
2320
+ B.observedAttributes = [
1597
2321
  "dashboard-id",
1598
2322
  "api-key",
1599
2323
  "user-id",
@@ -1604,55 +2328,62 @@ L.observedAttributes = [
1604
2328
  "height",
1605
2329
  "page-id",
1606
2330
  "tab-id",
2331
+ // v1 (kept for backward compat)
1607
2332
  "hide-filters",
1608
- "hide-export"
2333
+ "hide-export",
2334
+ // v2 visibility
2335
+ "hide-global-filters",
2336
+ "hide-inline-filters",
2337
+ "hide-text",
2338
+ "hide-header",
2339
+ "hide-background"
1609
2340
  ];
1610
- let T = L;
1611
- customElements.get("deepspot-dashboard") || customElements.define("deepspot-dashboard", T);
1612
- const A = class A extends HTMLElement {
2341
+ let j = B;
2342
+ customElements.get("deepspot-dashboard") || customElements.define("deepspot-dashboard", j);
2343
+ const G = class G extends HTMLElement {
1613
2344
  constructor() {
1614
2345
  super(...arguments), this.instance = null, this.isConnected_ = !1;
1615
2346
  }
1616
2347
  connectedCallback() {
1617
- this.isConnected_ = !0, F(), this.style.display = "block", this.renderRoot = document.createElement("div"), this.renderRoot.className = "ds-embed-root", this.appendChild(this.renderRoot), this.mount();
2348
+ this.isConnected_ = !0, q(), this.style.display = "block", this.renderRoot = document.createElement("div"), this.renderRoot.className = "ds-embed-root", this.appendChild(this.renderRoot), this.mount();
1618
2349
  }
1619
2350
  disconnectedCallback() {
1620
2351
  var e;
1621
2352
  this.isConnected_ = !1, (e = this.instance) == null || e.destroy(), this.instance = null;
1622
2353
  }
1623
2354
  attributeChangedCallback(e, t, s) {
1624
- var r;
1625
- t !== s && this.isConnected_ && ((r = this.instance) == null || r.destroy(), this.instance = null, this.mount());
2355
+ var i;
2356
+ t !== s && this.isConnected_ && ((i = this.instance) == null || i.destroy(), this.instance = null, this.mount());
1626
2357
  }
1627
2358
  async mount() {
1628
- const e = this.getAttribute("dashboard-id"), t = this.getAttribute("component-id"), s = this.getAttribute("api-key"), r = this.getAttribute("base-url") || "", i = this.getAttribute("user-id") || void 0, a = this.getAttribute("tenant-id") || void 0, d = this.getAttribute("theme") || "light", o = this.getAttribute("height") || "400px";
1629
- if (!e || !t || !s || !r) {
2359
+ const e = this.getAttribute("dashboard-id"), t = this.getAttribute("component-id"), s = this.getAttribute("api-key"), i = this.getAttribute("base-url") || "", r = this.getAttribute("user-id") || void 0, a = this.getAttribute("tenant-id") || void 0, o = this.getAttribute("theme") || "light", l = this.getAttribute("height") || "400px";
2360
+ if (!e || !t || !s || !i) {
1630
2361
  this.showError("Missing required attributes: dashboard-id, component-id, api-key, base-url");
1631
2362
  return;
1632
2363
  }
1633
- this.renderRoot.style.height = o, this.renderRoot.className = `ds-embed-root ds-theme-${d}`, this.showLoading();
2364
+ this.renderRoot.style.height = l, this.renderRoot.className = `ds-embed-root ds-theme-${o}`, this.showLoading();
1634
2365
  try {
1635
- const n = new S(r, s), b = await n.getEmbedToken({
2366
+ const d = new K(i, s), h = await d.getEmbedToken({
1636
2367
  dashboardId: e,
1637
2368
  embedType: "report",
1638
2369
  componentId: t,
1639
- userId: i,
2370
+ userId: r,
1640
2371
  tenantId: a
1641
- }), h = await n.getReportRender(e, t, b, {
2372
+ }), b = await d.getReportRender(e, t, h, {
1642
2373
  filters: {}
1643
- }), l = new H(this.renderRoot, d);
1644
- l.render(h, () => {
1645
- }), this.instance = new w({
2374
+ }), n = new he(this.renderRoot, o);
2375
+ n.render(b, () => {
2376
+ }), this.instance = new E({
1646
2377
  dashboardId: e,
1647
2378
  componentId: t,
1648
- token: b,
2379
+ token: h,
1649
2380
  embedType: "report",
1650
2381
  activeFilters: {},
1651
- apiClient: n,
1652
- renderer: l
2382
+ apiClient: d,
2383
+ renderer: n
1653
2384
  });
1654
- } catch (n) {
1655
- this.showError((n == null ? void 0 : n.message) || "Failed to load report");
2385
+ } catch (d) {
2386
+ this.showError((d == null ? void 0 : d.message) || "Failed to load report");
1656
2387
  }
1657
2388
  }
1658
2389
  showLoading() {
@@ -1685,7 +2416,7 @@ const A = class A extends HTMLElement {
1685
2416
  (e = this.instance) == null || e.refresh();
1686
2417
  }
1687
2418
  };
1688
- A.observedAttributes = [
2419
+ G.observedAttributes = [
1689
2420
  "dashboard-id",
1690
2421
  "component-id",
1691
2422
  "api-key",
@@ -1695,10 +2426,10 @@ A.observedAttributes = [
1695
2426
  "theme",
1696
2427
  "height"
1697
2428
  ];
1698
- let k = A;
1699
- customElements.get("deepspot-report") || customElements.define("deepspot-report", k);
1700
- customElements.get("deepspot-dashboard") || customElements.define("deepspot-dashboard", T);
1701
- customElements.get("deepspot-report") || customElements.define("deepspot-report", k);
2429
+ let z = G;
2430
+ customElements.get("deepspot-report") || customElements.define("deepspot-report", z);
2431
+ customElements.get("deepspot-dashboard") || customElements.define("deepspot-dashboard", j);
2432
+ customElements.get("deepspot-report") || customElements.define("deepspot-report", z);
1702
2433
  export {
1703
- U as DeepspotSDK
2434
+ ge as DeepspotSDK
1704
2435
  };