deepspotscreen-sdk 0.0.2 → 0.0.3

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 A {
1
+ class F {
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 i, a, o, d;
8
8
  const t = [
9
9
  e.dashboardId,
10
10
  e.embedType,
11
11
  (i = e.embedLevel) != null ? i : "",
12
12
  (a = e.componentId) != null ? a : "",
13
- (d = e.userId) != null ? d : ""
14
- ].join(":"), r = this.tokenCache.get(t);
15
- if (r && r.expiresAt > Date.now() + 6e4) return r.token;
16
- const s = await this.post(
13
+ (o = e.userId) != null ? o : ""
14
+ ].join(":"), s = this.tokenCache.get(t);
15
+ if (s && s.expiresAt > Date.now() + 6e4) return s.token;
16
+ const r = 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: (d = e.embedLevel) != null ? d : "dashboard",
22
22
  componentId: e.componentId,
23
23
  userId: e.userId,
24
24
  tenantId: e.tenantId,
@@ -27,36 +27,36 @@ class A {
27
27
  { "x-deepspot-api-key": this.apiKey }
28
28
  );
29
29
  return this.tokenCache.set(t, {
30
- token: s.token,
31
- expiresAt: new Date(s.expiresAt).getTime()
32
- }), s.token;
30
+ token: r.token,
31
+ expiresAt: new Date(r.expiresAt).getTime()
32
+ }), r.token;
33
33
  }
34
34
  // ── Dashboard Render (lazy — loads one tab at a time) ──────────────────────
35
- async getDashboardRender(e, t, r = {}) {
35
+ async getDashboardRender(e, t, s = {}) {
36
36
  var i;
37
- const s = new URLSearchParams({
37
+ const r = new URLSearchParams({
38
38
  embedType: "dashboard",
39
- embedLevel: (i = r.embedLevel) != null ? i : "dashboard"
39
+ embedLevel: (i = s.embedLevel) != null ? i : "dashboard"
40
40
  });
41
- return r.pageId && s.set("pageId", r.pageId), r.tabId && s.set("tabId", r.tabId), r.filters && Object.entries(r.filters).forEach(([a, d]) => {
42
- d != null && d !== "" && s.set(`filter[${a}]`, Array.isArray(d) ? d.join(",") : String(d));
41
+ return s.pageId && r.set("pageId", s.pageId), s.tabId && r.set("tabId", s.tabId), s.filters && Object.entries(s.filters).forEach(([a, o]) => {
42
+ o != null && o !== "" && r.set(`filter[${a}]`, Array.isArray(o) ? o.join(",") : String(o));
43
43
  }), this.get(
44
- `/dashboard-builder/embed/${e}/render?${s}`,
44
+ `/dashboard-builder/embed/${e}/render?${r}`,
45
45
  { "x-embed-token": t }
46
46
  );
47
47
  }
48
48
  // ── Single Report Render ────────────────────────────────────────────────────
49
- async getReportRender(e, t, r, s = {}) {
49
+ async getReportRender(e, t, s, r = {}) {
50
50
  const i = new URLSearchParams({
51
51
  embedType: "report",
52
52
  embedLevel: "report",
53
53
  componentId: t
54
54
  });
55
- return s.filters && Object.entries(s.filters).forEach(([a, d]) => {
56
- d != null && d !== "" && i.set(`filter[${a}]`, Array.isArray(d) ? d.join(",") : String(d));
55
+ return r.filters && Object.entries(r.filters).forEach(([a, o]) => {
56
+ o != null && o !== "" && i.set(`filter[${a}]`, Array.isArray(o) ? o.join(",") : String(o));
57
57
  }), this.get(
58
58
  `/dashboard-builder/embed/${e}/render?${i}`,
59
- { "x-embed-token": r }
59
+ { "x-embed-token": s }
60
60
  );
61
61
  }
62
62
  // ── API Key Management ──────────────────────────────────────────────────────
@@ -75,6 +75,18 @@ class A {
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, r, i) {
85
+ return this.get(
86
+ `/dashboard-builder/embed/${e}/table/${t}/data?page=${s}&pageSize=${r}`,
87
+ { "x-embed-token": i }
88
+ );
89
+ }
78
90
  // ── Filter Options ──────────────────────────────────────────────────────────
79
91
  /**
80
92
  * Fetches distinct option values for a dropdown / multi-select filter.
@@ -83,14 +95,14 @@ class A {
83
95
  * The embed token is sent so the backend can validate the caller has
84
96
  * access to this dashboard without requiring an admin JWT.
85
97
  */
86
- async getFilterOptions(e, t, r) {
98
+ async getFilterOptions(e, t, s) {
87
99
  try {
88
- const s = await this.get(
100
+ const r = await this.get(
89
101
  `/dashboard-builder/embed/${e}/filters/${t}/options`,
90
- { "x-embed-token": r }
102
+ { "x-embed-token": s }
91
103
  );
92
- return Array.isArray(s) ? s : Array.isArray(s == null ? void 0 : s.options) ? s.options : Array.isArray(s == null ? void 0 : s.data) ? s.data : [];
93
- } catch (s) {
104
+ 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 : [];
105
+ } catch (r) {
94
106
  return [];
95
107
  }
96
108
  }
@@ -99,36 +111,36 @@ class A {
99
111
  }
100
112
  // ── Private helpers ─────────────────────────────────────────────────────────
101
113
  async get(e, t = {}) {
102
- const r = await fetch(`${this.baseUrl}${e}`, {
114
+ const s = await fetch(`${this.baseUrl}${e}`, {
103
115
  method: "GET",
104
116
  headers: { "Content-Type": "application/json", ...t }
105
117
  });
106
- return this.handleResponse(r);
118
+ return this.handleResponse(s);
107
119
  }
108
- async post(e, t, r = {}) {
109
- const s = await fetch(`${this.baseUrl}${e}`, {
120
+ async post(e, t, s = {}) {
121
+ const r = await fetch(`${this.baseUrl}${e}`, {
110
122
  method: "POST",
111
- headers: { "Content-Type": "application/json", ...r },
123
+ headers: { "Content-Type": "application/json", ...s },
112
124
  body: JSON.stringify(t)
113
125
  });
114
- return this.handleResponse(s);
126
+ return this.handleResponse(r);
115
127
  }
116
128
  async delete(e, t = {}) {
117
- const r = await fetch(`${this.baseUrl}${e}`, {
129
+ const s = await fetch(`${this.baseUrl}${e}`, {
118
130
  method: "DELETE",
119
131
  headers: { "Content-Type": "application/json", ...t }
120
132
  });
121
- if (!r.ok) throw new Error(`Deepspot SDK: DELETE ${e} failed (${r.status})`);
133
+ if (!s.ok) throw new Error(`Deepspot SDK: DELETE ${e} failed (${s.status})`);
122
134
  }
123
135
  async handleResponse(e) {
124
136
  if (!e.ok) {
125
- let r = `HTTP ${e.status}`;
137
+ let s = `HTTP ${e.status}`;
126
138
  try {
127
- const s = await e.json();
128
- r = (s == null ? void 0 : s.message) || (s == null ? void 0 : s.error) || r;
129
- } catch (s) {
139
+ const r = await e.json();
140
+ s = (r == null ? void 0 : r.message) || (r == null ? void 0 : r.error) || s;
141
+ } catch (r) {
130
142
  }
131
- throw new Error(`Deepspot SDK: ${r}`);
143
+ throw new Error(`Deepspot SDK: ${s}`);
132
144
  }
133
145
  const t = await e.json();
134
146
  return (t == null ? void 0 : t.data) !== void 0 ? t.data : t;
@@ -136,8 +148,8 @@ class A {
136
148
  }
137
149
  class $ {
138
150
  constructor(e) {
139
- var t, r;
140
- this.destroyed = !1, this.refreshTimer = null, this.opts = e, this.filters = { ...e.activeFilters }, this.activePageId = (t = e.activePageId) != null ? t : "", this.activeTabId = (r = e.activeTabId) != null ? r : "";
151
+ var t, s;
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 : "";
141
153
  }
142
154
  /** Returns a copy of the currently applied filters */
143
155
  getActiveFilters() {
@@ -183,10 +195,10 @@ class $ {
183
195
  this.refreshTimer && clearTimeout(this.refreshTimer), this.refreshTimer = setTimeout(() => this.refresh(), 300);
184
196
  }
185
197
  async fetchData() {
186
- const { apiClient: e, dashboardId: t, componentId: r, token: s, embedType: i, embedLevel: a } = this.opts;
187
- return i === "report" && r ? e.getReportRender(t, r, s, {
198
+ const { apiClient: e, dashboardId: t, componentId: s, token: r, embedType: i, embedLevel: a } = this.opts;
199
+ return i === "report" && s ? e.getReportRender(t, s, r, {
188
200
  filters: this.filters
189
- }) : e.getDashboardRender(t, s, {
201
+ }) : e.getDashboardRender(t, r, {
190
202
  embedLevel: a,
191
203
  pageId: this.activePageId || void 0,
192
204
  tabId: this.activeTabId || void 0,
@@ -194,8 +206,8 @@ class $ {
194
206
  });
195
207
  }
196
208
  }
197
- const D = 24, x = 10, w = 12;
198
- class I {
209
+ const A = 24, w = 10, T = 12;
210
+ class S {
199
211
  /**
200
212
  * @param containerWidth Actual pixel width of the grid container.
201
213
  * @param minY Minimum y value across all components (normalises
@@ -206,44 +218,44 @@ class I {
206
218
  }
207
219
  /** Pixel width of one column unit */
208
220
  get colWidth() {
209
- return this.containerWidth / D;
221
+ return this.containerWidth / A;
210
222
  }
211
223
  /** Convert grid position {x,y,w,h} → CSS absolute pixel values */
212
224
  toPx(e) {
213
- const t = this.colWidth, r = w / 2;
225
+ const t = this.colWidth, s = T / 2;
214
226
  return {
215
- left: e.x * t + r,
216
- top: (e.y - this.minY) * x + r,
217
- width: e.w * t - w,
218
- height: e.h * x - w
227
+ left: e.x * t + s,
228
+ top: (e.y - this.minY) * w + s,
229
+ width: e.w * t - T,
230
+ height: e.h * w - T
219
231
  };
220
232
  }
221
233
  /** Total pixel height required to fit all positioned components */
222
234
  static totalHeight(e) {
223
235
  if (!e.length) return 400;
224
- const t = Math.min(...e.map((s) => s.y));
225
- return (Math.max(...e.map((s) => s.y + s.h)) - t) * x + 40;
236
+ const t = Math.min(...e.map((r) => r.y));
237
+ return (Math.max(...e.map((r) => r.y + r.h)) - t) * w + 40;
226
238
  }
227
239
  /** Apply absolute positioning styles directly to a DOM element */
228
240
  applyStyles(e, t) {
229
- const r = this.toPx(t);
230
- e.style.position = "absolute", e.style.left = `${r.left}px`, e.style.top = `${r.top}px`, e.style.width = `${r.width}px`, e.style.height = `${r.height}px`;
241
+ const s = this.toPx(t);
242
+ 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
243
  }
232
244
  }
233
- let T = null;
245
+ let k = null;
234
246
  function E() {
235
- return T || (T = import("./apexcharts.common-k3hLWpB8.js").then((p) => p.a)), T;
247
+ return k || (k = import("./apexcharts.common-k3hLWpB8.js").then((u) => u.a)), k;
236
248
  }
237
- class L {
249
+ class R {
238
250
  constructor(e) {
239
251
  this.chart = null, this.container = e;
240
252
  }
241
- async render(e, t, r, s) {
253
+ async render(e, t, s, r) {
242
254
  if (!t || t.length === 0) {
243
255
  this.renderEmpty(e.title);
244
256
  return;
245
257
  }
246
- const i = this.buildOptions(e, t, r, s);
258
+ const i = this.buildOptions(e, t, s, r);
247
259
  if (!i) {
248
260
  this.renderEmpty(e.title);
249
261
  return;
@@ -258,26 +270,26 @@ class L {
258
270
  if (a)
259
271
  try {
260
272
  this.chart && this.chart.destroy();
261
- const { default: d } = await E();
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>';
273
+ const { default: o } = await E();
274
+ this.chart = new o(a, i), this.chart.render();
275
+ } catch (o) {
276
+ console.error("[Deepspot SDK] ChartRenderer error:", o), a.innerHTML = '<div class="ds-chart-empty">Chart render error</div>';
265
277
  }
266
278
  }
267
- async update(e, t, r) {
279
+ async update(e, t, s) {
268
280
  if (!this.chart || !t || t.length === 0) {
269
- await this.render(e, t, r);
281
+ await this.render(e, t, s);
270
282
  return;
271
283
  }
272
- const { series: s, categories: i } = this.extractSeriesAndCategories(e, t);
284
+ const { series: r, categories: i } = this.extractSeriesAndCategories(e, t);
273
285
  try {
274
286
  this.chart.updateOptions({
275
- series: s,
287
+ series: r,
276
288
  xaxis: { categories: i },
277
- theme: { mode: r }
289
+ theme: { mode: s }
278
290
  });
279
291
  } catch (a) {
280
- this.render(e, t, r);
292
+ this.render(e, t, s);
281
293
  }
282
294
  }
283
295
  destroy() {
@@ -289,13 +301,13 @@ class L {
289
301
  this.chart = null;
290
302
  }
291
303
  // ── Private ─────────────────────────────────────────────────────────────────
292
- buildOptions(e, t, r, s) {
304
+ buildOptions(e, t, s, r) {
293
305
  const i = e.type;
294
- return i === "pie" || i === "donut" ? this.buildPieOptions(e, t, r, s) : i === "bar" || i === "line" || i === "area" ? this.buildCartesianOptions(e, t, r, s) : null;
306
+ return i === "pie" || i === "donut" ? this.buildPieOptions(e, t, s, r) : i === "bar" || i === "line" || i === "area" ? this.buildCartesianOptions(e, t, s, r) : null;
295
307
  }
296
- buildCartesianOptions(e, t, r, s) {
308
+ buildCartesianOptions(e, t, s, r) {
297
309
  var n;
298
- const { series: i, categories: a, xAxisLabel: d, yAxisLabel: o } = this.extractSeriesAndCategories(e, t), l = e.properties || {}, b = l.colors ? Object.values(l.colors) : ["#6366f1", "#8b5cf6", "#ec4899", "#f59e0b", "#10b981", "#3b82f6"], c = r === "dark";
310
+ const { series: i, categories: a, xAxisLabel: o, yAxisLabel: d } = this.extractSeriesAndCategories(e, t), c = e.properties || {}, h = c.colors ? Object.values(c.colors) : ["#6366f1", "#8b5cf6", "#ec4899", "#f59e0b", "#10b981", "#3b82f6"], l = s === "dark";
299
311
  return {
300
312
  chart: {
301
313
  type: e.type === "area" ? "area" : e.type === "line" ? "line" : "bar",
@@ -305,38 +317,38 @@ class L {
305
317
  fontFamily: "inherit",
306
318
  // Explicit height prevents ApexCharts from guessing the flex-child height
307
319
  // at render time (which can read as 0 before the browser settles layout).
308
- height: s != null ? s : "100%"
320
+ height: r != null ? r : "100%"
309
321
  },
310
- theme: { mode: r },
322
+ theme: { mode: s },
311
323
  series: i,
312
324
  xaxis: {
313
325
  categories: a,
314
- title: { text: d },
326
+ title: { text: o },
315
327
  labels: {
316
328
  rotate: a.length > 8 ? -45 : 0,
317
- style: { colors: c ? "#94a3b8" : "#6b7280", fontSize: "11px" }
329
+ style: { colors: l ? "#94a3b8" : "#6b7280", fontSize: "11px" }
318
330
  },
319
- axisBorder: { color: c ? "#334155" : "#e5e7eb" },
320
- axisTicks: { color: c ? "#334155" : "#e5e7eb" }
331
+ axisBorder: { color: l ? "#334155" : "#e5e7eb" },
332
+ axisTicks: { color: l ? "#334155" : "#e5e7eb" }
321
333
  },
322
334
  yaxis: {
323
- title: { text: o },
324
- labels: { style: { colors: c ? "#94a3b8" : "#6b7280", fontSize: "11px" } }
335
+ title: { text: d },
336
+ labels: { style: { colors: l ? "#94a3b8" : "#6b7280", fontSize: "11px" } }
325
337
  },
326
- colors: b,
338
+ colors: h,
327
339
  legend: {
328
- show: i.length > 1 || ((n = l.showLegend) != null ? n : !1),
340
+ show: i.length > 1 || ((n = c.showLegend) != null ? n : !1),
329
341
  position: "bottom",
330
- labels: { colors: c ? "#94a3b8" : "#6b7280" }
342
+ labels: { colors: l ? "#94a3b8" : "#6b7280" }
331
343
  },
332
344
  grid: {
333
- borderColor: c ? "#1e293b" : "#f3f4f6",
345
+ borderColor: l ? "#1e293b" : "#f3f4f6",
334
346
  strokeDashArray: 4,
335
347
  padding: {
336
348
  bottom: a.length > 8 ? 60 : 10
337
349
  }
338
350
  },
339
- tooltip: { theme: r },
351
+ tooltip: { theme: s },
340
352
  stroke: {
341
353
  curve: "smooth",
342
354
  width: e.type === "bar" ? 0 : 2
@@ -351,29 +363,29 @@ class L {
351
363
  }
352
364
  };
353
365
  }
354
- buildPieOptions(e, t, r, s) {
355
- const i = e.properties || {}, a = t.length > 0 ? Object.keys(t[0]) : [], d = a[0] || "label", o = a[1] || "value", l = t.map((h) => {
356
- var f;
357
- return String((f = h[d]) != null ? f : "");
358
- }), b = t.map((h) => Number(h[o]) || 0), c = r === "dark", n = i.colors ? Object.values(i.colors) : ["#6366f1", "#8b5cf6", "#ec4899", "#f59e0b", "#10b981", "#3b82f6"];
366
+ buildPieOptions(e, t, s, r) {
367
+ const i = e.properties || {}, a = t.length > 0 ? Object.keys(t[0]) : [], o = a[0] || "label", d = a[1] || "value", c = t.map((b) => {
368
+ var p;
369
+ return String((p = b[o]) != null ? p : "");
370
+ }), h = t.map((b) => Number(b[d]) || 0), l = s === "dark", n = i.colors ? Object.values(i.colors) : ["#6366f1", "#8b5cf6", "#ec4899", "#f59e0b", "#10b981", "#3b82f6"];
359
371
  return {
360
372
  chart: {
361
373
  type: e.type,
362
374
  toolbar: { show: !1 },
363
375
  background: "transparent",
364
376
  fontFamily: "inherit",
365
- height: s != null ? s : "100%"
377
+ height: r != null ? r : "100%"
366
378
  },
367
- theme: { mode: r },
368
- series: b,
369
- labels: l,
379
+ theme: { mode: s },
380
+ series: h,
381
+ labels: c,
370
382
  colors: n,
371
383
  legend: {
372
384
  position: "bottom",
373
- labels: { colors: c ? "#94a3b8" : "#6b7280" }
385
+ labels: { colors: l ? "#94a3b8" : "#6b7280" }
374
386
  },
375
- tooltip: { theme: r },
376
- dataLabels: { enabled: l.length <= 8 },
387
+ tooltip: { theme: s },
388
+ dataLabels: { enabled: c.length <= 8 },
377
389
  plotOptions: {
378
390
  pie: {
379
391
  donut: { size: e.type === "donut" ? "65%" : "0%" }
@@ -382,38 +394,38 @@ class L {
382
394
  };
383
395
  }
384
396
  extractSeriesAndCategories(e, t) {
385
- const r = e.properties || {}, s = t.length > 0 ? Object.keys(t[0]) : [], i = r.xAxis || s[0] || "x";
397
+ const s = e.properties || {}, r = t.length > 0 ? Object.keys(t[0]) : [], i = s.xAxis || r[0] || "x";
386
398
  let a = [];
387
- if (r.selectedYAxisColumn)
399
+ if (s.selectedYAxisColumn)
388
400
  try {
389
- const n = typeof r.selectedYAxisColumn == "string" ? JSON.parse(r.selectedYAxisColumn) : r.selectedYAxisColumn;
401
+ const n = typeof s.selectedYAxisColumn == "string" ? JSON.parse(s.selectedYAxisColumn) : s.selectedYAxisColumn;
390
402
  Array.isArray(n) && (a = n.map(
391
- (h) => typeof h == "string" ? { column: h } : h
403
+ (b) => typeof b == "string" ? { column: b } : b
392
404
  ));
393
405
  } catch (n) {
394
406
  }
395
- if (!a.length && r.yAxis) {
396
- const n = r.yAxis;
397
- a = (Array.isArray(n) ? n : [n]).map((f) => ({ column: String(f) }));
407
+ if (!a.length && s.yAxis) {
408
+ const n = s.yAxis;
409
+ a = (Array.isArray(n) ? n : [n]).map((p) => ({ column: String(p) }));
398
410
  }
399
- !a.length && s.length > 1 && (a = s.slice(1).map((n) => ({ column: n })));
400
- const d = t.map((n) => {
401
- var h;
402
- return String((h = n[i]) != null ? h : "");
403
- }), o = t.length > 0 ? Object.keys(t[0]) : [], l = a.map((n) => {
404
- const h = o.includes(n.column) ? n.column : null, f = h ? null : o.find((u) => u.includes(n.column) || n.column.includes(u)), g = !h && !f ? o.find((u) => {
411
+ !a.length && r.length > 1 && (a = r.slice(1).map((n) => ({ column: n })));
412
+ const o = t.map((n) => {
413
+ var b;
414
+ return String((b = n[i]) != null ? b : "");
415
+ }), d = t.length > 0 ? Object.keys(t[0]) : [], c = a.map((n) => {
416
+ const b = d.includes(n.column) ? n.column : null, p = b ? null : d.find((g) => g.includes(n.column) || n.column.includes(g)), m = !b && !p ? d.find((g) => {
405
417
  var y;
406
- return u !== i && !isNaN(Number((y = t[0]) == null ? void 0 : y[u]));
407
- }) : null, m = h || f || g || n.column;
418
+ return g !== i && !isNaN(Number((y = t[0]) == null ? void 0 : y[g]));
419
+ }) : null, f = b || p || m || n.column;
408
420
  return {
409
421
  name: n.label || n.column.replace(/_/g, " "),
410
- data: t.map((u) => {
411
- const y = u[m];
422
+ data: t.map((g) => {
423
+ const y = g[f];
412
424
  return y != null ? Number(y) : null;
413
425
  })
414
426
  };
415
- }), b = r.xAxisLabel || i.replace(/_/g, " "), c = r.yAxisLabel || (l.length === 1 ? l[0].name : "Values");
416
- return { series: l, categories: d, xAxisLabel: b, yAxisLabel: c };
427
+ }), h = s.xAxisLabel || i.replace(/_/g, " "), l = s.yAxisLabel || (c.length === 1 ? c[0].name : "Values");
428
+ return { series: c, categories: o, xAxisLabel: h, yAxisLabel: l };
417
429
  }
418
430
  renderEmpty(e) {
419
431
  this.container.innerHTML = `
@@ -424,34 +436,126 @@ class L {
424
436
  `;
425
437
  }
426
438
  }
427
- class R {
428
- render(e, t, r) {
429
- var l;
430
- if (!r || r.length === 0) {
439
+ class L {
440
+ constructor() {
441
+ this.columns = [], this.allData = [], this.currentRows = [], this.totalRows = 0, this.currentPage = 1, this.currentPageSize = 10, this.searchTerm = "", this.isLoading = !1;
442
+ }
443
+ // ── Public API ─────────────────────────────────────────────────────────────
444
+ render(e, t, s, r) {
445
+ var h;
446
+ this.container = e, this.component = t, this.fetchPage = r, this.searchTerm = "", this.currentPage = 1, this.currentPageSize = 10;
447
+ const i = s && !Array.isArray(s) && "rows" in s;
448
+ if (i) {
449
+ const l = s;
450
+ this.currentRows = l.rows, this.allData = [], this.totalRows = l.total, this.currentPage = l.page, this.currentPageSize = l.pageSize;
451
+ } else
452
+ this.allData = s || [], this.currentRows = [], this.totalRows = this.allData.length, this.currentPage = 1;
453
+ if (i && s.rows.length === 0 && s.total === 0 || !i && this.allData.length === 0) {
431
454
  e.innerHTML = `
432
455
  <div class="ds-table-card">
433
- <div class="ds-table-title">${t.title || ""}</div>
456
+ <div class="ds-table-header-row">
457
+ <span class="ds-table-dot"></span>
458
+ <div class="ds-table-title">${this.escape(t.title || "")}</div>
459
+ </div>
434
460
  <div class="ds-chart-empty">No data available</div>
435
461
  </div>
436
462
  `;
437
463
  return;
438
464
  }
439
- const s = Object.keys(r[0]), i = ((l = t.properties) == null ? void 0 : l.columns) || [], a = i.length ? i.filter((b) => s.includes(b)) : s, d = a.map((b) => `<th>${this.formatHeader(b)}</th>`).join(""), o = r.map((b) => `<tr>${a.map((n) => {
440
- const h = b[n];
441
- return `<td title="${this.escape(String(h != null ? h : ""))}">${this.escape(this.formatValue(h))}</td>`;
442
- }).join("")}</tr>`).join("");
443
- e.innerHTML = `
465
+ const a = i ? s.rows[0] : this.allData[0], o = a ? Object.keys(a) : [], d = ((h = t.properties) == null ? void 0 : h.columns) || [], c = d.length ? d.filter((l) => o.includes(l)) : [];
466
+ this.columns = c.length ? c : o, this.paint();
467
+ }
468
+ // ── Rendering ──────────────────────────────────────────────────────────────
469
+ paint() {
470
+ const { rows: e, startNum: t } = this.getPageRows(), s = Math.max(1, Math.ceil(this.totalRows / this.currentPageSize)), r = (this.currentPage - 1) * this.currentPageSize + 1, i = this.fetchPage ? Math.min(r - 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, b) => {
471
+ const p = this.columns.map((m) => {
472
+ const f = n[m];
473
+ return `<td title="${this.escape(String(f != null ? f : ""))}">${this.escape(this.formatValue(f))}</td>`;
474
+ }).join("");
475
+ return `<tr><td class="ds-table-sno">${t + b}</td>${p}</tr>`;
476
+ }).join(""), d = this.currentPageSize, c = [10, 25, 50, 100].map((n) => `<option value="${n}"${n === d ? " selected" : ""}>${n}</option>`).join(""), h = this.currentPage <= 1, l = this.currentPage >= s;
477
+ this.container.innerHTML = `
444
478
  <div class="ds-table-card">
445
- <div class="ds-table-title">${t.title || ""}</div>
479
+ <div class="ds-table-header-row">
480
+ <div class="ds-table-title-wrap">
481
+ <span class="ds-table-dot"></span>
482
+ <span class="ds-table-title">${this.escape(this.component.title || "")}</span>
483
+ </div>
484
+ </div>
446
485
  <div class="ds-table-scroll">
447
486
  <table class="ds-table">
448
- <thead><tr>${d}</tr></thead>
487
+ <thead><tr><th class="ds-table-sno-th">S.No</th>${a}</tr></thead>
449
488
  <tbody>${o}</tbody>
450
489
  </table>
451
490
  </div>
491
+ <div class="ds-table-footer">
492
+ <div class="ds-table-info">
493
+ <span>${r.toLocaleString()}–${i.toLocaleString()} of ${this.totalRows.toLocaleString()}</span>
494
+ <span class="ds-table-rows-label">Rows:</span>
495
+ <select class="ds-table-page-size">${c}</select>
496
+ </div>
497
+ <div class="ds-table-pagination">
498
+ <button class="ds-table-pg-btn" data-action="first" ${h ? "disabled" : ""}>&#171;</button>
499
+ <button class="ds-table-pg-btn" data-action="prev" ${h ? "disabled" : ""}>Previous</button>
500
+ <span class="ds-table-pg-info">Page ${this.currentPage} of ${s}</span>
501
+ <button class="ds-table-pg-btn" data-action="next" ${l ? "disabled" : ""}>Next</button>
502
+ <button class="ds-table-pg-btn" data-action="last" ${l ? "disabled" : ""}>&#187;</button>
503
+ </div>
504
+ </div>
505
+ ${this.isLoading ? '<div class="ds-table-loading-overlay"><div class="ds-embed-spinner"></div></div>' : ""}
452
506
  </div>
453
- `;
507
+ `, this.attachEvents();
508
+ }
509
+ attachEvents() {
510
+ const e = this.container.querySelector(".ds-table-search");
511
+ e == null || e.addEventListener("input", () => {
512
+ this.searchTerm = e.value, this.currentPage = 1, this.fetchPage || (this.totalRows = this.filteredRows().length, this.paint());
513
+ });
514
+ const t = this.container.querySelector(".ds-table-page-size");
515
+ t == null || t.addEventListener("change", () => {
516
+ this.currentPageSize = parseInt(t.value, 10), this.currentPage = 1, this.fetchPage ? this.loadPage(1) : (this.totalRows = this.filteredRows().length, this.paint());
517
+ }), this.container.querySelectorAll("[data-action]").forEach((s) => {
518
+ s.addEventListener("click", () => {
519
+ if (s.disabled) return;
520
+ const r = Math.max(1, Math.ceil(this.totalRows / this.currentPageSize)), i = s.dataset.action;
521
+ let a = this.currentPage;
522
+ i === "first" ? a = 1 : i === "prev" ? a = Math.max(1, this.currentPage - 1) : i === "next" ? a = Math.min(r, this.currentPage + 1) : i === "last" && (a = r), (a !== this.currentPage || i === "first" || i === "last") && (this.currentPage = a, this.fetchPage ? this.loadPage(a) : this.paint());
523
+ });
524
+ });
525
+ }
526
+ // ── Server-side page load ──────────────────────────────────────────────────
527
+ async loadPage(e) {
528
+ if (this.fetchPage) {
529
+ this.isLoading = !0, this.currentPage = e, this.paint();
530
+ try {
531
+ const t = await this.fetchPage(e, this.currentPageSize);
532
+ this.currentRows = t.rows || [], this.totalRows = Number(t.total) || this.currentRows.length, this.currentPage = Number(t.page) || e;
533
+ } catch (t) {
534
+ console.error("[Deepspot SDK] TableRenderer: page fetch failed", t);
535
+ } finally {
536
+ this.isLoading = !1, this.paint();
537
+ }
538
+ }
454
539
  }
540
+ // ── Data helpers ───────────────────────────────────────────────────────────
541
+ getPageRows() {
542
+ const e = (this.currentPage - 1) * this.currentPageSize + 1;
543
+ if (this.fetchPage)
544
+ return { rows: this.currentRows, startNum: e };
545
+ const t = this.filteredRows(), s = (this.currentPage - 1) * this.currentPageSize;
546
+ return { rows: t.slice(s, s + this.currentPageSize), startNum: e };
547
+ }
548
+ filteredRows() {
549
+ if (!this.searchTerm) return this.allData;
550
+ const e = this.searchTerm.toLowerCase();
551
+ return this.allData.filter(
552
+ (t) => this.columns.some((s) => {
553
+ var r;
554
+ return String((r = t[s]) != null ? r : "").toLowerCase().includes(e);
555
+ })
556
+ );
557
+ }
558
+ // ── Formatters ─────────────────────────────────────────────────────────────
455
559
  formatHeader(e) {
456
560
  return e.replace(/_/g, " ").replace(/\b\w/g, (t) => t.toUpperCase());
457
561
  }
@@ -462,39 +566,39 @@ class R {
462
566
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
463
567
  }
464
568
  }
465
- class F {
466
- render(e, t, r) {
467
- const s = t.properties || {};
569
+ class C {
570
+ render(e, t, s) {
571
+ const r = t.properties || {};
468
572
  let i = null;
469
- if (r && r.length > 0) {
470
- const h = r[0], f = s.metric || Object.keys(h)[0], g = h[f];
471
- if (g !== void 0)
472
- i = g;
573
+ if (s && s.length > 0) {
574
+ const b = s[0], p = r.metric || Object.keys(b)[0], m = b[p];
575
+ if (m !== void 0)
576
+ i = m;
473
577
  else {
474
- const m = Object.keys(h).find(
475
- (u) => u.includes(f) || f.includes(u)
578
+ const f = Object.keys(b).find(
579
+ (g) => g.includes(p) || p.includes(g)
476
580
  );
477
- i = h[m != null ? m : Object.keys(h)[0]];
581
+ i = b[f != null ? f : Object.keys(b)[0]];
478
582
  }
479
583
  }
480
- const a = this.formatValue(i, s), d = s.backgroundColor || "", o = s.textColor || "", l = t.title || "", b = d ? `background:${d};border-color:${d};` : "", c = o ? `color:${o};` : "", n = o ? `color:${o};opacity:0.7;` : "";
584
+ const a = this.formatValue(i, r), o = r.backgroundColor || "", d = r.textColor || "", c = t.title || "", h = o ? `background:${o};border-color:${o};` : "", l = d ? `color:${d};` : "", n = d ? `color:${d};opacity:0.7;` : "";
481
585
  e.innerHTML = `
482
- <div class="ds-card"${b ? ` style="${b}"` : ""}>
483
- <div class="ds-card-label"${n ? ` style="${n}"` : ""}>${l}</div>
484
- <div class="ds-card-value"${c ? ` style="${c}"` : ""}>${a}</div>
586
+ <div class="ds-card"${h ? ` style="${h}"` : ""}>
587
+ <div class="ds-card-label"${n ? ` style="${n}"` : ""}>${c}</div>
588
+ <div class="ds-card-value"${l ? ` style="${l}"` : ""}>${a}</div>
485
589
  </div>
486
590
  `;
487
591
  }
488
592
  formatValue(e, t) {
489
593
  if (e == null) return "—";
490
- const r = Number(e);
491
- if (isNaN(r)) return String(e);
492
- const s = (t == null ? void 0 : t.prefix) || (t == null ? void 0 : t.currencySymbol) || "", i = (t == null ? void 0 : t.suffix) || "";
594
+ const s = Number(e);
595
+ if (isNaN(s)) return String(e);
596
+ const r = (t == null ? void 0 : t.prefix) || (t == null ? void 0 : t.currencySymbol) || "", i = (t == null ? void 0 : t.suffix) || "";
493
597
  let a;
494
- return Math.abs(r) >= 1e6 ? a = (r / 1e6).toFixed(1) + "M" : Math.abs(r) >= 1e3 ? a = (r / 1e3).toFixed(1) + "K" : a = r % 1 === 0 ? r.toLocaleString() : r.toFixed(2), `${s}${a}${i}`;
598
+ 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}`;
495
599
  }
496
600
  }
497
- class P {
601
+ class D {
498
602
  constructor(e, t) {
499
603
  this.currentValues = {}, this.container = e, this.onFilterChange = t;
500
604
  }
@@ -503,42 +607,42 @@ class P {
503
607
  this.container.style.display = "none";
504
608
  return;
505
609
  }
506
- this.container.style.display = "", this.currentValues = { ...t }, this.container.innerHTML = `<div class="ds-filter-bar">${e.map((r) => this.renderFilter(r, t[r.applyToField || r.filterId])).join("")}</div>`, this.attachListeners(e);
610
+ this.container.style.display = "", this.currentValues = { ...t }, this.container.innerHTML = `<div class="ds-filter-bar">${e.map((s) => this.renderFilter(s, t[s.applyToField || s.filterId])).join("")}</div>`, this.attachListeners(e);
507
611
  }
508
612
  /**
509
613
  * Populate a dropdown / multi-select with options fetched from the API.
510
614
  * Called asynchronously after the filter bar is rendered.
511
615
  */
512
616
  updateOptions(e, t) {
513
- const r = this.container.querySelector(
617
+ const s = this.container.querySelector(
514
618
  `select[data-filter-id="${e}"]`
515
619
  );
516
- if (!r) return;
517
- const s = r.value;
518
- r.innerHTML = '<option value="">All</option>' + t.map(
620
+ if (!s) return;
621
+ const r = s.value;
622
+ s.innerHTML = '<option value="">All</option>' + t.map(
519
623
  (i) => `<option value="${this.escAttr(i)}">${this.escText(i)}</option>`
520
- ).join(""), s && t.includes(s) && (r.value = s);
624
+ ).join(""), r && t.includes(r) && (s.value = r);
521
625
  }
522
626
  /** Update the stored values without re-rendering (for programmatic setFilter) */
523
627
  updateValues(e) {
524
- Object.assign(this.currentValues, e), Object.entries(e).forEach(([t, r]) => {
525
- const s = this.container.querySelector(`[data-filter-id="${t}"]`);
526
- s && r !== void 0 && (s.value = String(r));
628
+ Object.assign(this.currentValues, e), Object.entries(e).forEach(([t, s]) => {
629
+ const r = this.container.querySelector(`[data-filter-id="${t}"]`);
630
+ r && s !== void 0 && (r.value = String(s));
527
631
  });
528
632
  }
529
633
  // ── Private ─────────────────────────────────────────────────────────────────
530
634
  renderFilter(e, t) {
531
- const r = `ds-filter-${e.filterId}`, s = `<label class="ds-filter-label" for="${r}">${e.label}</label>`;
635
+ const s = `ds-filter-${e.filterId}`, r = `<label class="ds-filter-label" for="${s}">${e.label}</label>`;
532
636
  switch (e.type) {
533
637
  case "dropdown":
534
638
  return `
535
639
  <div class="ds-filter-item">
536
- ${s}
537
- <select class="ds-filter-select" id="${r}" data-filter-id="${e.filterId}">
640
+ ${r}
641
+ <select class="ds-filter-select" id="${s}" data-filter-id="${e.filterId}">
538
642
  <option value="">All</option>
539
- ${(e.options || []).map((d) => `
540
- <option value="${this.escAttr(d)}" ${t === d ? "selected" : ""}>
541
- ${this.escText(d)}
643
+ ${(e.options || []).map((o) => `
644
+ <option value="${this.escAttr(o)}" ${t === o ? "selected" : ""}>
645
+ ${this.escText(o)}
542
646
  </option>
543
647
  `).join("")}
544
648
  </select>
@@ -546,10 +650,10 @@ class P {
546
650
  case "multi-select":
547
651
  return `
548
652
  <div class="ds-filter-item">
549
- ${s}
550
- <select class="ds-filter-select" id="${r}" data-filter-id="${e.filterId}" multiple size="1">
551
- ${(e.options || []).map((d) => `
552
- <option value="${this.escAttr(d)}">${this.escText(d)}</option>
653
+ ${r}
654
+ <select class="ds-filter-select" id="${s}" data-filter-id="${e.filterId}" multiple size="1">
655
+ ${(e.options || []).map((o) => `
656
+ <option value="${this.escAttr(o)}">${this.escText(o)}</option>
553
657
  `).join("")}
554
658
  </select>
555
659
  </div>`;
@@ -557,7 +661,7 @@ class P {
557
661
  const i = (t == null ? void 0 : t.from) || "", a = (t == null ? void 0 : t.to) || "";
558
662
  return `
559
663
  <div class="ds-filter-item">
560
- ${s}
664
+ ${r}
561
665
  <div class="ds-date-range-inputs">
562
666
  <input type="date" class="ds-filter-input"
563
667
  data-filter-id="${e.filterId}" data-date-part="from"
@@ -571,8 +675,8 @@ class P {
571
675
  case "text-input":
572
676
  return `
573
677
  <div class="ds-filter-item">
574
- ${s}
575
- <input type="text" class="ds-filter-input" id="${r}"
678
+ ${r}
679
+ <input type="text" class="ds-filter-input" id="${s}"
576
680
  data-filter-id="${e.filterId}"
577
681
  value="${this.escAttr(String(t != null ? t : ""))}"
578
682
  placeholder="Search..." />
@@ -580,8 +684,8 @@ class P {
580
684
  case "number-input":
581
685
  return `
582
686
  <div class="ds-filter-item">
583
- ${s}
584
- <input type="number" class="ds-filter-input" id="${r}"
687
+ ${r}
688
+ <input type="number" class="ds-filter-input" id="${s}"
585
689
  data-filter-id="${e.filterId}"
586
690
  value="${this.escAttr(String(t != null ? t : ""))}" />
587
691
  </div>`;
@@ -591,21 +695,21 @@ class P {
591
695
  }
592
696
  attachListeners(e) {
593
697
  const t = {};
594
- this.container.querySelectorAll("[data-filter-id]").forEach((r) => {
595
- const s = r.dataset.filterId, i = r.dataset.datePart, a = e.find((o) => o.filterId === s), d = () => {
596
- let o;
698
+ this.container.querySelectorAll("[data-filter-id]").forEach((s) => {
699
+ const r = s.dataset.filterId, i = s.dataset.datePart, a = e.find((d) => d.filterId === r), o = () => {
700
+ let d;
597
701
  if ((a == null ? void 0 : a.type) === "date-range" && i)
598
- t[s] = t[s] || {}, t[s][i] = r.value, o = { ...t[s] };
702
+ t[r] = t[r] || {}, t[r][i] = s.value, d = { ...t[r] };
599
703
  else if ((a == null ? void 0 : a.type) === "multi-select") {
600
- const l = r;
601
- o = Array.from(l.selectedOptions).map((b) => b.value).filter(Boolean);
704
+ const c = s;
705
+ d = Array.from(c.selectedOptions).map((h) => h.value).filter(Boolean);
602
706
  } else
603
- o = r.value;
604
- this.currentValues[s] = o, this.onFilterChange(s, o);
707
+ d = s.value;
708
+ this.currentValues[r] = d, this.onFilterChange(r, d);
605
709
  };
606
- r.addEventListener(
710
+ s.addEventListener(
607
711
  (a == null ? void 0 : a.type) === "text-input" ? "input" : "change",
608
- d
712
+ o
609
713
  );
610
714
  });
611
715
  }
@@ -616,14 +720,14 @@ class P {
616
720
  return e.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
617
721
  }
618
722
  }
619
- class O {
723
+ class z {
620
724
  constructor(e, t) {
621
- this.activePageId = "", this.activeTabId = "", this.activeFilters = {}, this.chartRenderers = /* @__PURE__ */ new Map(), this.tableRenderer = new R(), this.cardRenderer = new F(), this.isLoadingTab = !1, this.root = e, this.opts = t, this.activeFilters = { ...t.initialFilters };
725
+ this.activePageId = "", this.activeTabId = "", this.activeFilters = {}, this.chartRenderers = /* @__PURE__ */ new Map(), this.tableRenderer = new L(), this.cardRenderer = new C(), this.isLoadingTab = !1, this.root = e, this.opts = t, this.activeFilters = { ...t.initialFilters };
622
726
  }
623
727
  // ── Initial full render ───────────────────────────────────────────────────
624
728
  render(e) {
625
- var t, r;
626
- this.renderData = e, this.activePageId = e.activePage, this.activeTabId = e.activeTab, this.buildShell(), this.renderNavigation(), this.renderFilterBar(), this.renderGrid(), (r = (t = this.opts).onReady) == null || r.call(t);
729
+ var t, s;
730
+ this.renderData = e, this.activePageId = e.activePage, this.activeTabId = e.activeTab, this.buildShell(), this.renderNavigation(), this.renderFilterBar(), this.renderGrid(), (s = (t = this.opts).onReady) == null || s.call(t);
627
731
  }
628
732
  // ── Called after lazy tab fetch completes ─────────────────────────────────
629
733
  update(e) {
@@ -640,29 +744,62 @@ class O {
640
744
  this.chartRenderers.forEach((e) => e.destroy()), this.chartRenderers.clear(), this.root.innerHTML = "";
641
745
  }
642
746
  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
- (r) => import("./jspdf.es.min-Ge0fRUwj.js").then((s) => s.j).then(({ jsPDF: s }) => {
647
- const i = new s({ orientation: "landscape", unit: "px" });
648
- i.addImage(r.toDataURL("image/png"), "PNG", 0, 0, i.internal.pageSize.width, 0), i.save(`${this.renderData.dashboard.name || "dashboard"}.pdf`);
649
- })
650
- )
747
+ var n, b;
748
+ const e = this.root.querySelector("#ds-grid");
749
+ if (!e) return;
750
+ const t = this.root.style.height, s = this.root.style.overflow;
751
+ this.root.style.height = "auto", this.root.style.overflow = "visible";
752
+ const r = this.root.querySelector("#ds-canvas"), i = (n = r == null ? void 0 : r.style.height) != null ? n : "", a = (b = r == null ? void 0 : r.style.overflow) != null ? b : "";
753
+ r && (r.style.height = "auto", r.style.overflow = "visible");
754
+ const o = Array.from(e.querySelectorAll(".ds-table-scroll")), d = o.map((p) => ({
755
+ el: p,
756
+ overflow: p.style.overflow,
757
+ maxHeight: p.style.maxHeight,
758
+ height: p.style.height
759
+ }));
760
+ o.forEach((p) => {
761
+ p.style.overflow = "visible", p.style.maxHeight = "none", p.style.height = "auto";
762
+ });
763
+ const c = e.offsetWidth, h = parseInt(e.style.height, 10) || e.offsetHeight, l = e.getBoundingClientRect().top + window.scrollY;
764
+ import("./html2canvas.esm-CzwMv54K.js").then(
765
+ ({ default: p }) => p(e, {
766
+ scale: 2,
767
+ useCORS: !0,
768
+ allowTaint: !0,
769
+ logging: !1,
770
+ width: c,
771
+ height: h,
772
+ windowWidth: c,
773
+ windowHeight: h,
774
+ scrollX: 0,
775
+ scrollY: -l
776
+ }).then((m) => {
777
+ this.root.style.height = t, this.root.style.overflow = s, r && (r.style.height = i, r.style.overflow = a), d.forEach(({ el: f, overflow: g, maxHeight: y, height: v }) => {
778
+ f.style.overflow = g, f.style.maxHeight = y, f.style.height = v;
779
+ }), import("./jspdf.es.min-Ge0fRUwj.js").then((f) => f.j).then(({ jsPDF: f }) => {
780
+ const g = m.width / 2, y = m.height / 2, v = new f({
781
+ orientation: g >= y ? "landscape" : "portrait",
782
+ unit: "px",
783
+ format: [g, y]
784
+ });
785
+ v.addImage(m.toDataURL("image/png"), "PNG", 0, 0, g, y), v.save(`${this.renderData.dashboard.name || "dashboard"}.pdf`);
786
+ });
787
+ })
651
788
  );
652
789
  }
653
790
  exportCSV() {
654
791
  this.renderData.components.forEach((e) => {
655
792
  const t = this.renderData.data[e.id];
656
793
  if (!(t != null && t.length) || !["table", "bar", "line", "area"].includes(e.type)) return;
657
- const r = Object.keys(t[0]), s = [r.join(","), ...t.map(
658
- (a) => r.map((d) => {
659
- var o;
660
- return JSON.stringify((o = a[d]) != null ? o : "");
794
+ const s = Object.keys(t[0]), r = [s.join(","), ...t.map(
795
+ (a) => s.map((o) => {
796
+ var d;
797
+ return JSON.stringify((d = a[o]) != null ? d : "");
661
798
  }).join(",")
662
799
  )].join(`
663
800
  `);
664
801
  Object.assign(document.createElement("a"), {
665
- href: URL.createObjectURL(new Blob([s], { type: "text/csv" })),
802
+ href: URL.createObjectURL(new Blob([r], { type: "text/csv" })),
666
803
  download: `${e.title || e.id}.csv`
667
804
  }).click();
668
805
  });
@@ -673,11 +810,11 @@ class O {
673
810
  }
674
811
  // ── Shell ─────────────────────────────────────────────────────────────────
675
812
  buildShell() {
676
- const e = this.opts.embedLevel, t = this.renderData.dashboard.pages, r = e === "dashboard" && t.length > 1, s = e === "page" || e === "dashboard";
813
+ const e = this.opts.embedLevel, t = this.renderData.dashboard.pages, s = e === "dashboard" && t.length > 1, r = e === "page" || e === "dashboard";
677
814
  this.root.innerHTML = `
678
815
  ${this.opts.hideExport ? "" : '<div class="ds-toolbar" id="ds-toolbar"></div>'}
679
- ${r ? '<nav class="ds-page-nav" id="ds-page-nav"></nav>' : ""}
680
- ${s ? '<nav class="ds-page-nav" id="ds-tab-nav"></nav>' : ""}
816
+ ${s ? '<nav class="ds-page-nav" id="ds-page-nav"></nav>' : ""}
817
+ ${r ? '<nav class="ds-page-nav" id="ds-tab-nav"></nav>' : ""}
681
818
  <div id="ds-filter-container"></div>
682
819
  <div class="ds-canvas" id="ds-canvas">
683
820
  <div class="ds-grid" id="ds-grid"></div>
@@ -688,19 +825,19 @@ class O {
688
825
  </div>
689
826
  `, this.root.style.position = "relative", this.opts.hideExport || this.buildExportToolbar();
690
827
  const i = this.root.querySelector("#ds-filter-container");
691
- this.filterRenderer = new P(i, (a, d) => {
692
- var b, c;
693
- const o = this.renderData.filters.find((n) => n.filterId === a), l = (o == null ? void 0 : o.applyToField) || a;
694
- this.activeFilters[l] = d, (c = (b = this.opts).onFilterChange) == null || c.call(b, this.activeFilters), this.opts.onTabSwitch(this.activePageId, this.activeTabId);
828
+ this.filterRenderer = new D(i, (a, o) => {
829
+ var h, l;
830
+ const d = this.renderData.filters.find((n) => n.filterId === a), c = (d == null ? void 0 : d.applyToField) || a;
831
+ this.activeFilters[c] = o, (l = (h = this.opts).onFilterChange) == null || l.call(h, this.activeFilters), this.opts.onTabSwitch(this.activePageId, this.activeTabId);
695
832
  });
696
833
  }
697
834
  buildExportToolbar() {
698
- var t, r;
835
+ var t, s;
699
836
  const e = this.root.querySelector("#ds-toolbar");
700
837
  e && (e.innerHTML = `
701
838
  <button class="ds-toolbar-btn" id="ds-btn-pdf">⬇ PDF</button>
702
- <button class="ds-toolbar-btn" id="ds-btn-csv">⬇ CSV</button>
703
- `, (t = e.querySelector("#ds-btn-pdf")) == null || t.addEventListener("click", () => this.exportPDF()), (r = e.querySelector("#ds-btn-csv")) == null || r.addEventListener("click", () => this.exportCSV()));
839
+ <button class="ds-toolbar-btn" id="ds-btn-csv" style="display:none">⬇ CSV</button>
840
+ `, (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
841
  }
705
842
  // ── Navigation ────────────────────────────────────────────────────────────
706
843
  renderNavigation() {
@@ -713,9 +850,9 @@ class O {
713
850
  data-page-id="${t.pageId}">${t.title}</button>
714
851
  `).join(""), e.querySelectorAll(".ds-page-tab").forEach((t) => {
715
852
  t.addEventListener("click", () => {
716
- var s, i;
717
- const r = t.dataset.pageId;
718
- r === this.activePageId && !this.isLoadingTab || this.triggerTabSwitch(r, (i = (s = this.getTabsForPage(r)[0]) == null ? void 0 : s.id) != null ? i : "");
853
+ var r, i;
854
+ const s = t.dataset.pageId;
855
+ s === this.activePageId && !this.isLoadingTab || this.triggerTabSwitch(s, (i = (r = this.getTabsForPage(s)[0]) == null ? void 0 : r.id) != null ? i : "");
719
856
  });
720
857
  }));
721
858
  }
@@ -724,17 +861,17 @@ class O {
724
861
  t && this.buildTabButtons(t, e);
725
862
  }
726
863
  buildTabButtons(e, t) {
727
- const r = this.getTabsForPage(t);
728
- if (r.length <= 1) {
864
+ const s = this.getTabsForPage(t);
865
+ if (s.length <= 1) {
729
866
  e.style.display = "none";
730
867
  return;
731
868
  }
732
- e.style.display = "", e.innerHTML = r.map((s) => `
733
- <button class="ds-page-tab ${s.id === this.activeTabId ? "ds-active" : ""}"
734
- data-tab-id="${s.id}" data-page-id="${t}">${s.title}</button>
735
- `).join(""), e.querySelectorAll(".ds-page-tab").forEach((s) => {
736
- s.addEventListener("click", () => {
737
- const i = s.dataset.tabId, a = s.dataset.pageId;
869
+ e.style.display = "", e.innerHTML = s.map((r) => `
870
+ <button class="ds-page-tab ${r.id === this.activeTabId ? "ds-active" : ""}"
871
+ data-tab-id="${r.id}" data-page-id="${t}">${r.title}</button>
872
+ `).join(""), e.querySelectorAll(".ds-page-tab").forEach((r) => {
873
+ r.addEventListener("click", () => {
874
+ const i = r.dataset.tabId, a = r.dataset.pageId;
738
875
  i === this.activeTabId && a === this.activePageId && !this.isLoadingTab || this.triggerTabSwitch(a, i);
739
876
  });
740
877
  });
@@ -775,45 +912,47 @@ class O {
775
912
  this.hideTabSpinner();
776
913
  const e = this.root.querySelector("#ds-grid");
777
914
  if (!e) return;
778
- this.chartRenderers.forEach((l) => l.destroy()), this.chartRenderers.clear();
915
+ this.chartRenderers.forEach((c) => c.destroy()), this.chartRenderers.clear();
779
916
  const t = this.renderData.components;
780
917
  if (!t.length) {
781
918
  e.style.height = "200px", e.innerHTML = '<div class="ds-chart-empty" style="padding-top:80px;">No components on this tab.</div>';
782
919
  return;
783
920
  }
784
- const r = e.clientWidth || this.root.clientWidth || 800, s = t.map((l) => l.position), i = s.length ? Math.min(...s.map((l) => l.y)) : 0, a = new I(r, i);
785
- e.style.height = `${I.totalHeight(s)}px`, e.innerHTML = "";
786
- const d = 36, o = [];
787
- t.forEach((l) => {
788
- const b = document.createElement("div");
789
- b.className = "ds-component-wrapper", b.dataset.componentId = l.id, a.applyStyles(b, l.position), e.appendChild(b);
790
- const c = a.toPx(l.position), n = Math.max(50, c.height - d);
791
- o.push(this.renderComponent(b, l, n));
792
- }), Promise.all(o).catch(() => {
921
+ const s = e.clientWidth || this.root.clientWidth || 800, r = t.map((c) => c.position), i = r.length ? Math.min(...r.map((c) => c.y)) : 0, a = new S(s, i);
922
+ e.style.height = `${S.totalHeight(r)}px`, e.innerHTML = "";
923
+ const o = 36, d = [];
924
+ t.forEach((c) => {
925
+ const h = document.createElement("div");
926
+ h.className = "ds-component-wrapper", h.dataset.componentId = c.id, a.applyStyles(h, c.position), e.appendChild(h);
927
+ const l = a.toPx(c.position), n = Math.max(50, l.height - o);
928
+ d.push(this.renderComponent(h, c, n));
929
+ }), Promise.all(d).catch(() => {
793
930
  });
794
931
  }
795
- async renderComponent(e, t, r) {
796
- var a, d;
797
- const s = this.renderData.data[t.id] || [], i = this.opts.theme;
932
+ async renderComponent(e, t, s) {
933
+ var a, o;
934
+ const r = this.renderData.data[t.id] || [], i = this.opts.theme;
798
935
  switch (t.type) {
799
936
  case "bar":
800
937
  case "line":
801
938
  case "pie":
802
939
  case "donut":
803
940
  case "area": {
804
- const o = new L(e);
805
- await o.render(t, s, i, r), this.chartRenderers.set(t.id, o);
941
+ const d = new R(e);
942
+ await d.render(t, r, i, s), this.chartRenderers.set(t.id, d);
806
943
  break;
807
944
  }
808
- case "table":
809
- this.tableRenderer.render(e, t, s);
945
+ case "table": {
946
+ const d = this.opts.onFetchTablePage ? (c, h) => this.opts.onFetchTablePage(t.id, c, h) : void 0;
947
+ this.tableRenderer.render(e, t, r, d);
810
948
  break;
949
+ }
811
950
  case "number-card":
812
- this.cardRenderer.render(e, t, s);
951
+ this.cardRenderer.render(e, t, r);
813
952
  break;
814
953
  case "text": {
815
- const o = Object.entries(((a = t.properties) == null ? void 0 : a.style) || {}).map(([l, b]) => `${l}:${b}`).join(";");
816
- e.innerHTML = `<div style="${o};padding:8px;">${((d = t.properties) == null ? void 0 : d.content) || ""}</div>`;
954
+ const d = Object.entries(((a = t.properties) == null ? void 0 : a.style) || {}).map(([c, h]) => `${c}:${h}`).join(";");
955
+ e.innerHTML = `<div style="${d};padding:8px;">${((o = t.properties) == null ? void 0 : o.content) || ""}</div>`;
817
956
  break;
818
957
  }
819
958
  }
@@ -829,43 +968,43 @@ class O {
829
968
  }
830
969
  // ── Helpers ───────────────────────────────────────────────────────────────
831
970
  getTabsForPage(e) {
832
- var t, r;
833
- return (r = (t = this.renderData.dashboard.pages.find((s) => s.pageId === e)) == null ? void 0 : t.tabs) != null ? r : [];
971
+ var t, s;
972
+ return (s = (t = this.renderData.dashboard.pages.find((r) => r.pageId === e)) == null ? void 0 : t.tabs) != null ? s : [];
834
973
  }
835
974
  }
836
- class j {
975
+ class O {
837
976
  constructor(e, t) {
838
- this.chartRenderer = null, this.tableRenderer = new R(), this.cardRenderer = new F(), this.root = e, this.theme = t;
977
+ this.chartRenderer = null, this.tableRenderer = new L(), this.cardRenderer = new C(), this.root = e, this.theme = t;
839
978
  }
840
979
  render(e, t) {
841
- const r = e.components[0];
842
- if (!r) {
980
+ const s = e.components[0];
981
+ if (!s) {
843
982
  this.root.innerHTML = `<div class="ds-embed-error">
844
983
  <div class="ds-embed-error-icon">⚠</div>
845
984
  <div>Component not found.</div>
846
985
  </div>`;
847
986
  return;
848
987
  }
849
- const s = e.data[r.id] || [];
850
- this.renderComponent(r, s), t == null || t();
988
+ const r = e.data[s.id] || [];
989
+ this.renderComponent(s, r), t == null || t();
851
990
  }
852
991
  update(e) {
853
992
  const t = e.components[0];
854
993
  if (!t) return;
855
- const r = e.data[t.id] || [];
994
+ const s = e.data[t.id] || [];
856
995
  switch (t.type) {
857
996
  case "bar":
858
997
  case "line":
859
998
  case "pie":
860
999
  case "donut":
861
1000
  case "area":
862
- this.chartRenderer ? this.chartRenderer.update(t, r, this.theme) : this.renderComponent(t, r);
1001
+ this.chartRenderer ? this.chartRenderer.update(t, s, this.theme) : this.renderComponent(t, s);
863
1002
  break;
864
1003
  case "table":
865
- this.tableRenderer.render(this.root, t, r);
1004
+ this.tableRenderer.render(this.root, t, s);
866
1005
  break;
867
1006
  case "number-card":
868
- this.cardRenderer.render(this.root, t, r);
1007
+ this.cardRenderer.render(this.root, t, s);
869
1008
  break;
870
1009
  }
871
1010
  }
@@ -874,14 +1013,14 @@ class j {
874
1013
  (e = this.chartRenderer) == null || e.destroy(), this.chartRenderer = null, this.root.innerHTML = "";
875
1014
  }
876
1015
  renderComponent(e, t) {
877
- var r;
1016
+ var s;
878
1017
  switch (e.type) {
879
1018
  case "bar":
880
1019
  case "line":
881
1020
  case "pie":
882
1021
  case "donut":
883
1022
  case "area":
884
- (r = this.chartRenderer) == null || r.destroy(), this.chartRenderer = new L(this.root), this.chartRenderer.render(e, t, this.theme);
1023
+ (s = this.chartRenderer) == null || s.destroy(), this.chartRenderer = new R(this.root), this.chartRenderer.render(e, t, this.theme);
885
1024
  break;
886
1025
  case "table":
887
1026
  this.tableRenderer.render(this.root, e, t);
@@ -894,12 +1033,12 @@ class j {
894
1033
  }
895
1034
  }
896
1035
  }
897
- let S = !1;
898
- function M() {
899
- if (!(S || typeof document == "undefined")) {
900
- S = !0;
1036
+ let I = !1;
1037
+ function j() {
1038
+ if (!(I || typeof document == "undefined")) {
1039
+ I = !0;
901
1040
  try {
902
- const p = `/* ─────────────────────────────────────────────────────────────────────────────
1041
+ const u = `/* ─────────────────────────────────────────────────────────────────────────────
903
1042
  Deepspot SDK — Base Embed Styles
904
1043
  Injected once into the host page's <head> by the SDK.
905
1044
  All selectors are scoped under .ds-embed-* to avoid leaking into host styles.
@@ -1182,6 +1321,7 @@ function M() {
1182
1321
  overflow: hidden;
1183
1322
  display: flex;
1184
1323
  flex-direction: column;
1324
+ position: relative;
1185
1325
  }
1186
1326
 
1187
1327
  .ds-theme-dark .ds-table-card {
@@ -1189,21 +1329,100 @@ function M() {
1189
1329
  border-color: #334155;
1190
1330
  }
1191
1331
 
1332
+ /* ── Table header: dot + title on left, search on right ──────────────────────*/
1333
+ .ds-table-header-row {
1334
+ display: flex;
1335
+ align-items: center;
1336
+ justify-content: space-between;
1337
+ padding: 10px 14px 8px;
1338
+ flex-shrink: 0;
1339
+ gap: 8px;
1340
+ border-bottom: 1px solid #f3f4f6;
1341
+ }
1342
+
1343
+ .ds-theme-dark .ds-table-header-row {
1344
+ border-bottom-color: #334155;
1345
+ }
1346
+
1347
+ .ds-table-title-wrap {
1348
+ display: flex;
1349
+ align-items: center;
1350
+ gap: 6px;
1351
+ min-width: 0;
1352
+ }
1353
+
1354
+ .ds-table-dot {
1355
+ width: 8px;
1356
+ height: 8px;
1357
+ border-radius: 50%;
1358
+ background: #6366f1;
1359
+ flex-shrink: 0;
1360
+ }
1361
+
1192
1362
  .ds-table-title {
1193
- padding: 10px 14px 4px;
1194
1363
  font-size: 13px;
1195
1364
  font-weight: 600;
1196
1365
  color: #374151;
1197
- flex-shrink: 0;
1366
+ white-space: nowrap;
1367
+ overflow: hidden;
1368
+ text-overflow: ellipsis;
1198
1369
  }
1199
1370
 
1200
1371
  .ds-theme-dark .ds-table-title {
1201
1372
  color: #e2e8f0;
1202
1373
  }
1203
1374
 
1375
+ /* ── Search ──────────────────────────────────────────────────────────────────*/
1376
+ .ds-table-search-wrap {
1377
+ position: relative;
1378
+ flex-shrink: 0;
1379
+ }
1380
+
1381
+ .ds-table-search-icon {
1382
+ position: absolute;
1383
+ left: 8px;
1384
+ top: 50%;
1385
+ transform: translateY(-50%);
1386
+ width: 14px;
1387
+ height: 14px;
1388
+ color: #9ca3af;
1389
+ pointer-events: none;
1390
+ }
1391
+
1392
+ .ds-table-search {
1393
+ height: 30px;
1394
+ padding: 0 10px 0 28px;
1395
+ border: 1px solid #e5e7eb;
1396
+ border-radius: 6px;
1397
+ font-size: 12px;
1398
+ background: #f9fafb;
1399
+ color: #374151;
1400
+ width: 180px;
1401
+ outline: none;
1402
+ transition: border-color 0.15s, box-shadow 0.15s;
1403
+ }
1404
+
1405
+ .ds-table-search:focus {
1406
+ border-color: #6366f1;
1407
+ box-shadow: 0 0 0 2px rgba(99,102,241,0.15);
1408
+ background: #fff;
1409
+ }
1410
+
1411
+ .ds-theme-dark .ds-table-search {
1412
+ background: #0f172a;
1413
+ border-color: #334155;
1414
+ color: #e2e8f0;
1415
+ }
1416
+
1417
+ .ds-theme-dark .ds-table-search:focus {
1418
+ background: #1e293b;
1419
+ }
1420
+
1421
+ /* ── Scroll area ─────────────────────────────────────────────────────────────*/
1204
1422
  .ds-table-scroll {
1205
1423
  flex: 1;
1206
1424
  overflow: auto;
1425
+ min-height: 0;
1207
1426
  }
1208
1427
 
1209
1428
  .ds-table {
@@ -1212,6 +1431,21 @@ function M() {
1212
1431
  font-size: 12px;
1213
1432
  }
1214
1433
 
1434
+ .ds-table-sno-th {
1435
+ width: 48px;
1436
+ text-align: center !important;
1437
+ }
1438
+
1439
+ .ds-table-sno {
1440
+ text-align: center;
1441
+ color: #9ca3af;
1442
+ font-size: 11px;
1443
+ }
1444
+
1445
+ .ds-theme-dark .ds-table-sno {
1446
+ color: #64748b;
1447
+ }
1448
+
1215
1449
  .ds-table th {
1216
1450
  position: sticky;
1217
1451
  top: 0;
@@ -1253,7 +1487,123 @@ function M() {
1253
1487
  }
1254
1488
 
1255
1489
  .ds-theme-dark .ds-table tr:hover td {
1490
+ background: #0f172a;
1491
+ }
1492
+
1493
+ /* ── Footer: info + pagination ───────────────────────────────────────────────*/
1494
+ .ds-table-footer {
1495
+ display: flex;
1496
+ align-items: center;
1497
+ justify-content: space-between;
1498
+ padding: 8px 14px;
1499
+ border-top: 1px solid #f3f4f6;
1500
+ flex-shrink: 0;
1501
+ gap: 8px;
1502
+ flex-wrap: wrap;
1503
+ }
1504
+
1505
+ .ds-theme-dark .ds-table-footer {
1506
+ border-top-color: #334155;
1507
+ }
1508
+
1509
+ .ds-table-info {
1510
+ display: flex;
1511
+ align-items: center;
1512
+ gap: 8px;
1513
+ font-size: 12px;
1514
+ color: #6b7280;
1515
+ }
1516
+
1517
+ .ds-theme-dark .ds-table-info {
1518
+ color: #94a3b8;
1519
+ }
1520
+
1521
+ .ds-table-rows-label {
1522
+ margin-left: 4px;
1523
+ }
1524
+
1525
+ .ds-table-page-size {
1526
+ height: 28px;
1527
+ padding: 0 6px;
1528
+ border: 1px solid #e5e7eb;
1529
+ border-radius: 5px;
1530
+ font-size: 12px;
1531
+ background: #fff;
1532
+ color: #374151;
1533
+ cursor: pointer;
1534
+ outline: none;
1535
+ }
1536
+
1537
+ .ds-theme-dark .ds-table-page-size {
1538
+ background: #0f172a;
1539
+ border-color: #334155;
1540
+ color: #e2e8f0;
1541
+ }
1542
+
1543
+ .ds-table-pagination {
1544
+ display: flex;
1545
+ align-items: center;
1546
+ gap: 6px;
1547
+ }
1548
+
1549
+ .ds-table-pg-btn {
1550
+ height: 28px;
1551
+ padding: 0 10px;
1552
+ border: 1px solid #e5e7eb;
1553
+ border-radius: 5px;
1554
+ font-size: 12px;
1555
+ font-weight: 500;
1556
+ background: #fff;
1557
+ color: #374151;
1558
+ cursor: pointer;
1559
+ transition: background 0.12s, border-color 0.12s;
1560
+ white-space: nowrap;
1561
+ }
1562
+
1563
+ .ds-table-pg-btn:hover:not(:disabled) {
1564
+ background: #f3f4f6;
1565
+ border-color: #d1d5db;
1566
+ }
1567
+
1568
+ .ds-table-pg-btn:disabled {
1569
+ opacity: 0.4;
1570
+ cursor: not-allowed;
1571
+ }
1572
+
1573
+ .ds-theme-dark .ds-table-pg-btn {
1256
1574
  background: #1e293b;
1575
+ border-color: #334155;
1576
+ color: #e2e8f0;
1577
+ }
1578
+
1579
+ .ds-theme-dark .ds-table-pg-btn:hover:not(:disabled) {
1580
+ background: #0f172a;
1581
+ }
1582
+
1583
+ .ds-table-pg-info {
1584
+ font-size: 12px;
1585
+ color: #6b7280;
1586
+ white-space: nowrap;
1587
+ }
1588
+
1589
+ .ds-theme-dark .ds-table-pg-info {
1590
+ color: #94a3b8;
1591
+ }
1592
+
1593
+ /* ── Loading overlay while fetching a page ───────────────────────────────────*/
1594
+ .ds-table-loading-overlay {
1595
+ position: absolute;
1596
+ inset: 0;
1597
+ background: rgba(255,255,255,0.6);
1598
+ display: flex;
1599
+ align-items: center;
1600
+ justify-content: center;
1601
+ border-radius: 10px;
1602
+ z-index: 10;
1603
+ }
1604
+
1605
+ .ds-theme-dark .ds-table-loading-overlay {
1606
+ background: rgba(30,41,59,0.7);
1257
1607
  }
1258
1608
 
1259
1609
  /* ── KPI Number Card ───────────────────────────────────────────────────────── */
@@ -1335,102 +1685,103 @@ function M() {
1335
1685
  background: #0f172a;
1336
1686
  }
1337
1687
  `, e = document.createElement("style");
1338
- e.id = "deepspot-sdk-styles", e.textContent = p, document.head.appendChild(e);
1339
- } catch (p) {
1688
+ e.id = "deepspot-sdk-styles", e.textContent = u, document.head.appendChild(e);
1689
+ } catch (u) {
1340
1690
  }
1341
1691
  }
1342
1692
  }
1343
- function C(p) {
1344
- if (typeof p == "string") {
1345
- const e = document.querySelector(p);
1346
- if (!e) throw new Error(`Deepspot SDK: container "${p}" not found in DOM`);
1693
+ function P(u) {
1694
+ if (typeof u == "string") {
1695
+ const e = document.querySelector(u);
1696
+ if (!e) throw new Error(`Deepspot SDK: container "${u}" not found in DOM`);
1347
1697
  return e;
1348
1698
  }
1349
- return p;
1699
+ return u;
1350
1700
  }
1351
- class K {
1701
+ class M {
1352
1702
  constructor(e) {
1353
1703
  if (!e.apiKey) throw new Error("Deepspot SDK: apiKey is required");
1354
1704
  if (!e.baseUrl) throw new Error("Deepspot SDK: baseUrl is required");
1355
- this.apiClient = new A(e.baseUrl, e.apiKey), M();
1705
+ this.apiClient = new F(e.baseUrl, e.apiKey), j();
1356
1706
  }
1357
1707
  // ── Embed full dashboard ────────────────────────────────────────────────────
1358
1708
  async embedDashboard(e) {
1359
- var a, d, o, l, b;
1360
- const t = C(e.container), r = (a = e.embedLevel) != null ? a : "dashboard", s = (d = e.theme) != null ? d : "light";
1709
+ var a, o, d, c, h;
1710
+ const t = P(e.container), s = (a = e.embedLevel) != null ? a : "dashboard", r = (o = e.theme) != null ? o : "light";
1361
1711
  t.style.height = e.height || "600px", t.style.display = "block";
1362
- const i = this.createRoot(t, s);
1712
+ const i = this.createRoot(t, r);
1363
1713
  this.showLoading(i);
1364
1714
  try {
1365
- const c = await this.apiClient.getEmbedToken({
1715
+ const l = await this.apiClient.getEmbedToken({
1366
1716
  dashboardId: e.dashboardId,
1367
1717
  embedType: "dashboard",
1368
- embedLevel: r,
1718
+ embedLevel: s,
1369
1719
  userId: e.userId,
1370
1720
  tenantId: e.tenantId
1371
1721
  }), n = await this.apiClient.getDashboardRender(
1372
1722
  e.dashboardId,
1373
- c,
1723
+ l,
1374
1724
  {
1375
- embedLevel: r,
1725
+ embedLevel: s,
1376
1726
  pageId: e.pageId,
1377
1727
  tabId: e.tabId,
1378
1728
  filters: e.filters || {}
1379
1729
  }
1380
1730
  );
1381
- let h;
1382
- const f = new O(i, {
1383
- embedLevel: r,
1384
- theme: s,
1385
- hideFilters: (o = e.hideFilters) != null ? o : !1,
1386
- hideExport: (l = e.hideExport) != null ? l : !1,
1731
+ let b;
1732
+ const p = new z(i, {
1733
+ embedLevel: s,
1734
+ theme: r,
1735
+ hideFilters: (d = e.hideFilters) != null ? d : !1,
1736
+ hideExport: (c = e.hideExport) != null ? c : !1,
1387
1737
  initialFilters: e.filters || {},
1388
1738
  onFilterChange: e.onFilterChange,
1389
1739
  onReady: e.onReady,
1390
- onFetchFilterOptions: (g) => this.apiClient.getFilterOptions(e.dashboardId, g, c),
1391
- onTabSwitch: async (g, m) => {
1392
- var u, y, k;
1393
- (u = e.onTabSwitch) == null || u.call(e, g, m);
1740
+ onFetchFilterOptions: (m) => this.apiClient.getFilterOptions(e.dashboardId, m, l),
1741
+ onFetchTablePage: (m, f, g) => this.apiClient.getTablePage(e.dashboardId, m, f, g, l),
1742
+ onTabSwitch: async (m, f) => {
1743
+ var g, y, v;
1744
+ (g = e.onTabSwitch) == null || g.call(e, m, f);
1394
1745
  try {
1395
- const v = await this.apiClient.getDashboardRender(
1746
+ const x = await this.apiClient.getDashboardRender(
1396
1747
  e.dashboardId,
1397
- c,
1748
+ l,
1398
1749
  {
1399
- embedLevel: r,
1400
- pageId: g,
1401
- tabId: m,
1402
- filters: (k = (y = h == null ? void 0 : h.getActiveFilters()) != null ? y : e.filters) != null ? k : {}
1750
+ embedLevel: s,
1751
+ pageId: m,
1752
+ tabId: f,
1753
+ filters: (v = (y = b == null ? void 0 : b.getActiveFilters()) != null ? y : e.filters) != null ? v : {}
1403
1754
  }
1404
1755
  );
1405
- f.update(v);
1406
- } catch (v) {
1407
- console.error("Deepspot SDK: tab fetch failed", v);
1756
+ p.update(x);
1757
+ } catch (x) {
1758
+ console.error("Deepspot SDK: tab fetch failed", x);
1408
1759
  }
1409
1760
  }
1410
1761
  });
1411
- return f.render(n), h = new $({
1762
+ return p.render(n), b = new $({
1412
1763
  dashboardId: e.dashboardId,
1413
- token: c,
1764
+ token: l,
1414
1765
  embedType: "dashboard",
1415
- embedLevel: r,
1766
+ embedLevel: s,
1416
1767
  activePageId: n.activePage,
1417
1768
  activeTabId: n.activeTab,
1418
1769
  activeFilters: e.filters || {},
1419
1770
  apiClient: this.apiClient,
1420
- renderer: f,
1771
+ renderer: p,
1421
1772
  onFilterChange: e.onFilterChange
1422
- }), h;
1423
- } catch (c) {
1424
- throw this.showError(i, (c == null ? void 0 : c.message) || "Failed to load dashboard"), (b = e.onError) == null || b.call(e, (c == null ? void 0 : c.message) || "Failed to load dashboard"), c;
1773
+ }), b;
1774
+ } catch (l) {
1775
+ throw this.showError(i, (l == null ? void 0 : l.message) || "Failed to load dashboard"), (h = e.onError) == null || h.call(e, (l == null ? void 0 : l.message) || "Failed to load dashboard"), l;
1425
1776
  }
1426
1777
  }
1427
1778
  // ── Embed single report (component) ────────────────────────────────────────
1428
1779
  async embedReport(e) {
1429
- var s;
1430
- const t = C(e.container);
1780
+ var r;
1781
+ const t = P(e.container);
1431
1782
  t.style.height = e.height || "400px", t.style.display = "block";
1432
- const r = this.createRoot(t, e.theme || "light");
1433
- this.showLoading(r);
1783
+ const s = this.createRoot(t, e.theme || "light");
1784
+ this.showLoading(s);
1434
1785
  try {
1435
1786
  const i = await this.apiClient.getEmbedToken({
1436
1787
  dashboardId: e.dashboardId,
@@ -1443,25 +1794,25 @@ class K {
1443
1794
  e.componentId,
1444
1795
  i,
1445
1796
  { filters: e.filters || {} }
1446
- ), d = new j(r, e.theme || "light");
1447
- return d.render(a, e.onReady), new $({
1797
+ ), o = new O(s, e.theme || "light");
1798
+ return o.render(a, e.onReady), new $({
1448
1799
  dashboardId: e.dashboardId,
1449
1800
  componentId: e.componentId,
1450
1801
  token: i,
1451
1802
  embedType: "report",
1452
1803
  activeFilters: e.filters || {},
1453
1804
  apiClient: this.apiClient,
1454
- renderer: d
1805
+ renderer: o
1455
1806
  });
1456
1807
  } catch (i) {
1457
- throw this.showError(r, (i == null ? void 0 : i.message) || "Failed to load report"), (s = e.onError) == null || s.call(e, (i == null ? void 0 : i.message) || "Failed to load report"), i;
1808
+ 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;
1458
1809
  }
1459
1810
  }
1460
1811
  // ── Private helpers ─────────────────────────────────────────────────────────
1461
1812
  createRoot(e, t) {
1462
1813
  e.innerHTML = "";
1463
- const r = document.createElement("div");
1464
- return r.className = `ds-embed-root ds-theme-${t}`, r.style.width = "100%", r.style.height = "100%", e.appendChild(r), r;
1814
+ const s = document.createElement("div");
1815
+ return s.className = `ds-embed-root ds-theme-${t}`, s.style.width = "100%", s.style.height = "100%", e.appendChild(s), s;
1465
1816
  }
1466
1817
  showLoading(e) {
1467
1818
  e.innerHTML = `
@@ -1482,5 +1833,5 @@ class K {
1482
1833
  }
1483
1834
  }
1484
1835
  export {
1485
- K as DeepspotSDK
1836
+ M as DeepspotSDK
1486
1837
  };