@mmlogic/components 0.1.30 → 0.3.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.
@@ -22,7 +22,10 @@ export class MrdTable {
22
22
  this.outsideClickHandler = null;
23
23
  this.keydownHandler = null;
24
24
  // ── Props ──────────────────────────────────────────────────────────────────
25
- this.columns = [];
25
+ /** The VIEW or RELATED_VIEW layout item. Contains view config, dataClass, fromClass, actions etc. */
26
+ this.item = null;
27
+ /** Parent record id — required for RELATED_VIEW to build /{fromClass}/{parentId}/{dataClass}. */
28
+ this.parentId = '';
26
29
  /** Direct rows (non-paginated mode, used when totalElements === 0). */
27
30
  this.rows = [];
28
31
  this.locale = navigator.language;
@@ -34,16 +37,9 @@ export class MrdTable {
34
37
  this.rowHeight = 36;
35
38
  /** Height of the scroll container in px. */
36
39
  this.tableHeight = 500;
37
- /** Initial sort applied on load, e.g. "timestamp,desc" or "name".
38
- * Parsed by init() into sortField + sortDir. */
39
- this.defaultSort = '';
40
- /** Toolbar action buttons rendered above the table. */
41
- this.actions = [];
42
- /** Display label of the current view — shown in the toolbar center as a view picker trigger. */
43
- this.viewLabel = '';
44
- /** Alternative views available for this table; renders a dropdown when non-empty. */
45
- this.alternativeViews = [];
46
40
  // ── Internal state ─────────────────────────────────────────────────────────
41
+ /** Index into allViews[] for the currently displayed view. 0 = primary, 1+ = alternatives. */
42
+ this.activeViewIdx = 0;
47
43
  this.loadedPages = new Map();
48
44
  this.requestedPages = new Set();
49
45
  this.renderStart = 0;
@@ -86,13 +82,16 @@ export class MrdTable {
86
82
  totalElementsChanged(newVal) {
87
83
  this.renderEnd = Math.min(this.renderEnd, Math.max(0, newVal - 1));
88
84
  }
89
- /** Apply defaultSort when the prop changes (e.g. after a view switch). */
90
- defaultSortChanged(newVal) {
91
- this.applyDefaultSort(newVal);
85
+ /** Reset to primary view when the item prop is replaced from outside. */
86
+ itemChanged(newVal) {
87
+ var _a, _b;
88
+ this.activeViewIdx = 0;
89
+ this.applyDefaultSort((_b = (_a = newVal === null || newVal === void 0 ? void 0 : newVal.view) === null || _a === void 0 ? void 0 : _a.defaultSort) !== null && _b !== void 0 ? _b : '');
92
90
  }
93
91
  // ── Lifecycle ──────────────────────────────────────────────────────────────
94
92
  componentWillLoad() {
95
- this.applyDefaultSort(this.defaultSort);
93
+ var _a, _b, _c;
94
+ this.applyDefaultSort((_c = (_b = (_a = this.item) === null || _a === void 0 ? void 0 : _a.view) === null || _b === void 0 ? void 0 : _b.defaultSort) !== null && _c !== void 0 ? _c : '');
96
95
  }
97
96
  // ── Helpers ────────────────────────────────────────────────────────────────
98
97
  applyDefaultSort(defaultSort) {
@@ -124,14 +123,17 @@ export class MrdTable {
124
123
  this.colWidths = [];
125
124
  this.scrollTop = 0;
126
125
  this.renderStart = 0;
127
- // No BUFFER on init — only request what fits the visible area (page 0).
128
- // BUFFER is applied during scroll to pre-fetch the next page proactively.
129
- this.renderEnd = Math.max(0, Math.min(this.visibleCount() - 1, this.totalElements - 1));
126
+ // Always fill the visible viewport on init — totalElements may be stale from a
127
+ // previous view. setPage() clamps renderEnd when the page is shorter than pageSize.
128
+ this.renderEnd = this.visibleCount() - 1;
130
129
  const scroller = this.el.querySelector('.mrd-table__scroll');
131
130
  if (scroller)
132
131
  scroller.scrollTop = 0;
133
132
  this.aggregations = null;
134
133
  this.emitLoadAggregations();
134
+ // Always request page 0 — totalElements may be unknown (0) on first load.
135
+ this.mrdLoadPage.emit({ page: 0, sort: this.sortParam(), path: this.buildDataPath(), qs: this.buildQueryParams(0) });
136
+ this.requestedPages = new Set([0]);
135
137
  }
136
138
  /**
137
139
  * Inject the rows for a given page (0-based).
@@ -184,26 +186,167 @@ export class MrdTable {
184
186
  return '';
185
187
  return this.sortDir === 'desc' ? `${this.sortField},desc` : this.sortField;
186
188
  }
187
- colName(col) {
189
+ /** Stable ordered list: primary view first, then alternatives (from the item prop). */
190
+ get allViews() {
191
+ var _a, _b, _c, _d, _e, _f, _g;
192
+ if (!this.item)
193
+ return [];
194
+ const it = this.item;
195
+ return [
196
+ { label: (_e = (_d = (_c = (_a = it.label) !== null && _a !== void 0 ? _a : (_b = it.view) === null || _b === void 0 ? void 0 : _b.pluralLabel) !== null && _c !== void 0 ? _c : it.dataClass) !== null && _d !== void 0 ? _d : it.relatedClass) !== null && _e !== void 0 ? _e : '', dataClass: (_f = it.dataClass) !== null && _f !== void 0 ? _f : it.relatedClass, fromClass: it.fromClass, filterClass: it.filterClass, view: it.view },
197
+ ...((_g = it.alternativeViews) !== null && _g !== void 0 ? _g : []).map(av => {
198
+ var _a, _b, _c, _d;
199
+ return ({
200
+ label: (_d = (_c = (_a = av.label) !== null && _a !== void 0 ? _a : (_b = av.view) === null || _b === void 0 ? void 0 : _b.pluralLabel) !== null && _c !== void 0 ? _c : av.dataClass) !== null && _d !== void 0 ? _d : '',
201
+ dataClass: av.dataClass,
202
+ fromClass: av.fromClass,
203
+ filterClass: av.filterClass,
204
+ view: av.view,
205
+ });
206
+ }),
207
+ ];
208
+ }
209
+ /** Relative excel export path for the current view.
210
+ * VIEW: /excel/{dataClass}
211
+ * RELATED_VIEW: /excel/{fromClass}/{parentId}/{dataClass} */
212
+ buildExcelPath() {
188
213
  var _a, _b, _c, _d;
189
- return (_d = (_b = (_a = col.field) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : (_c = col.relation) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : '';
214
+ const v = this.allViews[this.activeViewIdx];
215
+ if (!v)
216
+ return '';
217
+ if (((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === 'RELATED_VIEW') {
218
+ return `/excel/${(_b = v.fromClass) !== null && _b !== void 0 ? _b : ''}/${this.parentId}/${(_c = v.dataClass) !== null && _c !== void 0 ? _c : ''}`;
219
+ }
220
+ return `/excel/${(_d = v.dataClass) !== null && _d !== void 0 ? _d : ''}`;
190
221
  }
191
- colDataType(col) {
222
+ buildActionDetail(action) {
223
+ var _a, _b, _c;
224
+ if (action === 'export') {
225
+ return { action, path: this.buildExcelPath(), qs: this.buildQueryParams(0) };
226
+ }
227
+ if (action === 'create') {
228
+ const v = this.allViews[this.activeViewIdx];
229
+ const parentPath = ((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === 'RELATED_VIEW'
230
+ ? `/${(_b = v === null || v === void 0 ? void 0 : v.fromClass) !== null && _b !== void 0 ? _b : ''}/${this.parentId}`
231
+ : null;
232
+ return { action, dataClass: (_c = v === null || v === void 0 ? void 0 : v.dataClass) !== null && _c !== void 0 ? _c : '', parentPath };
233
+ }
234
+ return { action };
235
+ }
236
+ /** Relative data path for the current view, without query string.
237
+ * VIEW: /{dataClass}
238
+ * RELATED_VIEW: /{fromClass}/{parentId}/{dataClass} */
239
+ buildDataPath() {
240
+ var _a, _b, _c, _d;
241
+ const v = this.allViews[this.activeViewIdx];
242
+ if (!v)
243
+ return '';
244
+ if (((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === 'RELATED_VIEW') {
245
+ return `/${(_b = v.fromClass) !== null && _b !== void 0 ? _b : ''}/${this.parentId}/${(_c = v.dataClass) !== null && _c !== void 0 ? _c : ''}`;
246
+ }
247
+ return `/${(_d = v.dataClass) !== null && _d !== void 0 ? _d : ''}`;
248
+ }
249
+ /** Build query params for a page request from current sort, view filters, filterClass and active column filters. */
250
+ buildQueryParams(page) {
251
+ var _a, _b, _c, _d, _e, _f, _g;
252
+ const v = this.allViews[this.activeViewIdx];
253
+ const p = new URLSearchParams();
254
+ if (page > 0)
255
+ p.set('page', String(page));
256
+ const sort = this.sortParam();
257
+ if (sort)
258
+ p.set('sort', sort);
259
+ const filterClass = v === null || v === void 0 ? void 0 : v.filterClass;
260
+ if (filterClass)
261
+ p.set('type', filterClass);
262
+ for (const f of ((_b = (_a = v === null || v === void 0 ? void 0 : v.view) === null || _a === void 0 ? void 0 : _a.filter) !== null && _b !== void 0 ? _b : [])) {
263
+ if (!f.name)
264
+ continue;
265
+ if (f.operator === 'EMPTY') {
266
+ p.set(f.name, '');
267
+ continue;
268
+ }
269
+ if (f.operator === 'NOT_EMPTY') {
270
+ p.set(f.name + '_notempty', 'true');
271
+ continue;
272
+ }
273
+ if (f.operator === 'STARTS_WITH') {
274
+ p.set(f.name + '_startswith', String((_c = f.value) !== null && _c !== void 0 ? _c : ''));
275
+ continue;
276
+ }
277
+ if (f.operator === 'FROM') {
278
+ p.set(f.name + '_from', String((_d = f.value) !== null && _d !== void 0 ? _d : ''));
279
+ continue;
280
+ }
281
+ if (f.operator === 'TO') {
282
+ p.set(f.name + '_to', String((_e = f.value) !== null && _e !== void 0 ? _e : ''));
283
+ continue;
284
+ }
285
+ if (f.value != null) {
286
+ p.set(f.name, String(f.value));
287
+ }
288
+ }
289
+ for (const f of this.activeFilters.values()) {
290
+ if (f.operator === 'isEmpty') {
291
+ p.set(f.field, '');
292
+ continue;
293
+ }
294
+ if (f.operator === 'isNotEmpty') {
295
+ p.set(f.field + '_notempty', 'true');
296
+ continue;
297
+ }
298
+ if (f.operator === 'startsWith') {
299
+ p.set(f.field + '_startswith', String((_f = f.value) !== null && _f !== void 0 ? _f : ''));
300
+ continue;
301
+ }
302
+ if ((_g = f.values) === null || _g === void 0 ? void 0 : _g.length) {
303
+ p.set(f.field, f.values.join(','));
304
+ continue;
305
+ }
306
+ if (f.value != null)
307
+ p.set(f.field, String(f.value));
308
+ if (f.from != null)
309
+ p.set(f.field + '_from', String(f.from));
310
+ if (f.to != null)
311
+ p.set(f.field + '_to', String(f.to));
312
+ }
313
+ return p.toString();
314
+ }
315
+ get columns() {
316
+ var _a, _b, _c;
317
+ return ((_c = (_b = (_a = this.allViews[this.activeViewIdx]) === null || _a === void 0 ? void 0 : _a.view) === null || _b === void 0 ? void 0 : _b.values) !== null && _c !== void 0 ? _c : []);
318
+ }
319
+ get tableActions() {
192
320
  var _a, _b;
321
+ const raw = (_b = (_a = this.item) === null || _a === void 0 ? void 0 : _a.actions) !== null && _b !== void 0 ? _b : [];
322
+ return (raw !== null && raw !== void 0 ? raw : []).reduce((acc, a) => {
323
+ if (a === 'NEW')
324
+ acc.push({ action: 'create', label: t('table_new_record', this.locale), icon: 'assets/sprites.svg#icon-plus', variant: 'primary' });
325
+ if (a === 'EXPORT')
326
+ acc.push({ action: 'export', label: t('table_export_excel', this.locale), icon: 'assets/sprites.svg#icon-file-excel' });
327
+ return acc;
328
+ }, []);
329
+ }
330
+ colName(col) {
331
+ var _a;
332
+ return (_a = col.name) !== null && _a !== void 0 ? _a : '';
333
+ }
334
+ colDataType(col) {
335
+ var _a;
193
336
  if (col.type === 'RELATION')
194
337
  return 'RELATION';
195
- return (_b = (_a = col.field) === null || _a === void 0 ? void 0 : _a.dataType) !== null && _b !== void 0 ? _b : 'TEXT';
338
+ return (_a = col.dataType) !== null && _a !== void 0 ? _a : 'TEXT';
196
339
  }
197
340
  // ── Aggregation helpers ────────────────────────────────────────────────────
198
341
  buildAggregationParams() {
199
342
  var _a;
200
343
  const groups = { sum: [], avg: [], count: [] };
201
344
  for (const col of this.columns) {
202
- if (col.type !== 'FIELD' || !((_a = col.field) === null || _a === void 0 ? void 0 : _a.aggregate))
345
+ if (col.type !== 'FIELD' || !col.aggregate)
203
346
  continue;
204
- const fn = col.field.aggregate.toLowerCase();
347
+ const fn = col.aggregate.toLowerCase();
205
348
  if (fn in groups)
206
- groups[fn].push(col.field.name);
349
+ groups[fn].push((_a = col.name) !== null && _a !== void 0 ? _a : '');
207
350
  }
208
351
  const params = {};
209
352
  if (groups.sum.length)
@@ -215,25 +358,25 @@ export class MrdTable {
215
358
  return Object.keys(params).length > 0 ? params : null;
216
359
  }
217
360
  emitLoadAggregations() {
218
- const params = this.buildAggregationParams();
219
- if (params)
220
- this.mrdLoadAggregations.emit(params);
361
+ const aggParams = this.buildAggregationParams();
362
+ if (aggParams)
363
+ this.mrdLoadAggregations.emit(Object.assign(Object.assign({}, aggParams), { path: this.buildDataPath(), qs: this.buildQueryParams(0) }));
221
364
  }
222
365
  renderAggregationValue(col) {
223
366
  var _a, _b;
224
- if (col.type !== 'FIELD' || !((_a = col.field) === null || _a === void 0 ? void 0 : _a.aggregate) || !this.aggregations)
367
+ if (col.type !== 'FIELD' || !col.aggregate || !this.aggregations)
225
368
  return '';
226
- const fn = col.field.aggregate.toLowerCase();
227
- const val = (_b = this.aggregations[fn]) === null || _b === void 0 ? void 0 : _b[col.field.name];
369
+ const fn = col.aggregate.toLowerCase();
370
+ const val = (_a = this.aggregations[fn]) === null || _a === void 0 ? void 0 : _a[(_b = col.name) !== null && _b !== void 0 ? _b : ''];
228
371
  if (val == null)
229
372
  return '';
230
- const dt = col.field.dataType;
373
+ const dt = col.dataType;
231
374
  if (dt === 'INTEGER')
232
375
  return formatNumber(val, this.locale, { maximumFractionDigits: 0 });
233
376
  if (dt === 'PERCENTAGE')
234
377
  return formatPercentage(val, this.locale);
235
- if (dt === 'CURRENCY' && col.field.currencyCode)
236
- return formatCurrency(val, col.field.currencyCode, this.locale);
378
+ if (dt === 'CURRENCY' && col.currencyCode)
379
+ return formatCurrency(val, col.currencyCode, this.locale);
237
380
  return formatNumber(val, this.locale);
238
381
  }
239
382
  // ── Reset pagination ───────────────────────────────────────────────────────
@@ -282,7 +425,7 @@ export class MrdTable {
282
425
  for (let p = firstPage; p <= lastPage; p++) {
283
426
  if (!this.loadedPages.has(p) && !next.has(p)) {
284
427
  next.add(p);
285
- this.mrdLoadPage.emit({ page: p, sort: this.sortParam() });
428
+ this.mrdLoadPage.emit({ page: p, sort: this.sortParam(), path: this.buildDataPath(), qs: this.buildQueryParams(p) });
286
429
  changed = true;
287
430
  }
288
431
  }
@@ -324,7 +467,7 @@ export class MrdTable {
324
467
  if (pageEnd < this.renderStart || pageStart > this.renderEnd)
325
468
  continue;
326
469
  next.add(page);
327
- this.mrdLoadPage.emit({ page, sort: this.sortParam() });
470
+ this.mrdLoadPage.emit({ page, sort: this.sortParam(), path: this.buildDataPath(), qs: this.buildQueryParams(page) });
328
471
  changed = true;
329
472
  }
330
473
  this.pendingPages.clear();
@@ -516,7 +659,6 @@ export class MrdTable {
516
659
  }
517
660
  this.activeFilters = next;
518
661
  this.closeFilterPopup();
519
- this.mrdFilter.emit({ filters: Array.from(this.activeFilters.values()) });
520
662
  this.aggregations = null;
521
663
  this.emitLoadAggregations();
522
664
  if (this.totalElements > 0) {
@@ -531,7 +673,6 @@ export class MrdTable {
531
673
  next.delete(name);
532
674
  this.activeFilters = next;
533
675
  this.closeFilterPopup();
534
- this.mrdFilter.emit({ filters: Array.from(this.activeFilters.values()) });
535
676
  this.aggregations = null;
536
677
  this.emitLoadAggregations();
537
678
  if (this.totalElements > 0) {
@@ -541,7 +682,6 @@ export class MrdTable {
541
682
  }
542
683
  clearAllFilters() {
543
684
  this.activeFilters = new Map();
544
- this.mrdFilter.emit({ filters: [] });
545
685
  this.aggregations = null;
546
686
  this.emitLoadAggregations();
547
687
  if (this.totalElements > 0) {
@@ -550,35 +690,37 @@ export class MrdTable {
550
690
  }
551
691
  }
552
692
  // ── View switcher ──────────────────────────────────────────────────────────
553
- handleViewSwitch(view) {
554
- this.mrdSwitchView.emit({ name: view.name, class: view.class });
693
+ handleViewSwitch(targetIdx) {
694
+ var _a, _b;
695
+ const target = this.allViews[targetIdx];
696
+ if (!(target === null || target === void 0 ? void 0 : target.view))
697
+ return;
698
+ this.activeViewIdx = targetIdx;
699
+ this.applyDefaultSort((_b = (_a = target.view) === null || _a === void 0 ? void 0 : _a.defaultSort) !== null && _b !== void 0 ? _b : '');
700
+ this.activeFilters = new Map();
701
+ this.init();
555
702
  }
556
703
  // ── Render: toolbar ────────────────────────────────────────────────────────
557
704
  renderToolbar() {
558
- var _a, _b;
559
705
  const filterCount = this.activeFilters.size;
560
- const hasActions = ((_a = this.actions) === null || _a === void 0 ? void 0 : _a.length) > 0;
561
- const hasViewSwitcher = !!this.viewLabel && ((_b = this.alternativeViews) === null || _b === void 0 ? void 0 : _b.length) > 0;
706
+ const actions = this.tableActions;
707
+ const allViews = this.allViews;
708
+ const hasActions = actions.length > 0;
709
+ const hasViewSwitcher = allViews.length > 1;
562
710
  return (h("div", { class: "mrd-table__toolbar" }, h("div", { class: "mrd-table__toolbar-left" }, h("button", { class: `mrd-table__action mrd-table__action--secondary mrd-table__filter-toggle${this.filterMode ? ' mrd-table__filter-toggle--active' : ''}`, onClick: () => this.handleFilterToggle() }, h("svg", { class: "mrd-table__action-icon", viewBox: "0 0 24 24", "aria-hidden": "true" }, h("path", { fill: "currentColor", d: "M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z" })), filterCount > 0 && h("span", { class: "mrd-table__filter-badge" }, filterCount), h("span", { class: "mrd-table__action-tooltip" }, this.filterMode ? t('table_filter_hide', this.locale) : t('table_filter', this.locale), filterCount > 0 ? ` (${filterCount} ${t('table_filter_active', this.locale)})` : '')), filterCount > 0 && (h("button", { class: "mrd-table__action mrd-table__action--secondary", onClick: () => this.clearAllFilters() }, h("svg", { class: "mrd-table__action-icon", viewBox: "0 0 24 24", "aria-hidden": "true" }, h("path", { fill: "currentColor", d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" })), h("span", { class: "mrd-table__action-tooltip" }, t('table_filter_clear_all', this.locale))))), hasViewSwitcher && (h("div", { class: "mrd-table__toolbar-center" }, h("select", { class: "mrd-table__view-select", onChange: (e) => {
563
- const sel = e.target;
564
- const view = this.alternativeViews.find(v => v.name === sel.value);
565
- if (view) {
566
- sel.selectedIndex = 0;
567
- this.handleViewSwitch(view);
568
- }
569
- } }, h("option", { value: "" }, this.viewLabel), this.alternativeViews.map(v => {
570
- var _a;
571
- return (h("option", { value: v.name }, (_a = v.label) !== null && _a !== void 0 ? _a : v.name));
572
- })))), hasActions && (h("div", { class: "mrd-table__toolbar-right" }, this.actions.map(a => {
711
+ const idx = parseInt(e.target.value, 10);
712
+ if (!isNaN(idx) && idx !== this.activeViewIdx)
713
+ this.handleViewSwitch(idx);
714
+ } }, allViews.map((v, i) => (h("option", { value: String(i), selected: i === this.activeViewIdx }, v.label)))))), hasActions && (h("div", { class: "mrd-table__toolbar-right" }, actions.map(a => {
573
715
  var _a;
574
- return (h("button", { class: `mrd-table__action mrd-table__action--${(_a = a.variant) !== null && _a !== void 0 ? _a : 'secondary'}`, disabled: a.disabled, onClick: () => this.mrdAction.emit({ action: a.action }) }, a.icon
716
+ return (h("button", { class: `mrd-table__action mrd-table__action--${(_a = a.variant) !== null && _a !== void 0 ? _a : 'secondary'}`, disabled: a.disabled, onClick: () => this.mrdAction.emit(this.buildActionDetail(a.action)) }, a.icon
575
717
  ? h("svg", { class: "mrd-table__action-icon", "aria-hidden": "true" }, h("use", { href: a.icon }))
576
718
  : a.label, h("span", { class: "mrd-table__action-tooltip" }, a.label)));
577
719
  })))));
578
720
  }
579
721
  // ── Render: filter popup ───────────────────────────────────────────────────
580
722
  renderFilterEditor(col) {
581
- var _a, _b, _c, _d, _e, _f, _g, _h;
723
+ var _a, _b, _c, _d, _e, _f, _g;
582
724
  const pf = (_a = this.pendingFilter) !== null && _a !== void 0 ? _a : {};
583
725
  const dataType = this.colDataType(col);
584
726
  if (NO_FILTER_TYPES.has(dataType)) {
@@ -594,19 +736,19 @@ export class MrdTable {
594
736
  ].map(opt => (h("label", { class: "mrd-table__filter-radio-label" }, h("input", { type: "radio", name: `bf-${this.openFilterCol}`, checked: !noValueOp && pf.value === opt.value, onChange: () => { this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: undefined, value: opt.value }); } }), t(opt.labelKey, this.locale)))), h("label", { class: "mrd-table__filter-radio-label" }, h("input", { type: "radio", name: `bf-${this.openFilterCol}`, checked: boolOp === 'isEmpty', onChange: () => { this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: 'isEmpty', value: undefined }); } }), t('filter_is_empty', this.locale)), h("label", { class: "mrd-table__filter-radio-label" }, h("input", { type: "radio", name: `bf-${this.openFilterCol}`, checked: boolOp === 'isNotEmpty', onChange: () => { this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: 'isNotEmpty', value: undefined }); } }), t('filter_is_not_empty', this.locale))));
595
737
  }
596
738
  if (dataType === 'LIST') {
597
- const items = (_c = (_b = col.field) === null || _b === void 0 ? void 0 : _b.listItems) !== null && _c !== void 0 ? _c : [];
598
- const selected = (_d = pf.values) !== null && _d !== void 0 ? _d : [];
739
+ const items = (_b = col.listItems) !== null && _b !== void 0 ? _b : [];
740
+ const selected = (_c = pf.values) !== null && _c !== void 0 ? _c : [];
599
741
  return (h("div", { class: "mrd-table__filter-list" }, h("div", { class: "mrd-table__filter-list-controls" }, h("button", { class: "mrd-table__filter-list-btn", onClick: () => { this.pendingFilter = Object.assign(Object.assign({}, pf), { values: items.map(i => i.key) }); } }, t('filter_select_all', this.locale)), h("button", { class: "mrd-table__filter-list-btn", onClick: () => { this.pendingFilter = Object.assign(Object.assign({}, pf), { values: [] }); } }, t('filter_select_none', this.locale))), items.map(item => (h("label", { class: "mrd-table__filter-checkbox-label" }, h("input", { type: "checkbox", checked: selected.includes(item.key), onChange: (e) => this.togglePendingValue(item.key, e.target.checked) }), item.label)))));
600
742
  }
601
743
  if (TEXT_TYPES.has(dataType) || dataType === 'RELATION') {
602
- const op = (_e = pf.operator) !== null && _e !== void 0 ? _e : 'startsWith';
744
+ const op = (_d = pf.operator) !== null && _d !== void 0 ? _d : 'startsWith';
603
745
  const noInput = op === 'isEmpty' || op === 'isNotEmpty';
604
746
  return (h("div", { class: "mrd-table__filter-editor" }, h("select", { class: "mrd-table__filter-select", onChange: (e) => this.setPending('operator', e.target.value) }, [
605
747
  { val: 'startsWith', labelKey: 'filter_starts_with' },
606
748
  { val: 'equals', labelKey: 'filter_equals' },
607
749
  { val: 'isEmpty', labelKey: 'filter_is_empty' },
608
750
  { val: 'isNotEmpty', labelKey: 'filter_is_not_empty' },
609
- ].map(o => h("option", { value: o.val, selected: op === o.val }, t(o.labelKey, this.locale)))), !noInput && (h("input", { type: "text", class: "mrd-table__filter-input", value: String((_f = pf.value) !== null && _f !== void 0 ? _f : ''), placeholder: t('filter_search_value', this.locale), onInput: (e) => this.setPending('value', e.target.value) }))));
751
+ ].map(o => h("option", { value: o.val, selected: op === o.val }, t(o.labelKey, this.locale)))), !noInput && (h("input", { type: "text", class: "mrd-table__filter-input", value: String((_e = pf.value) !== null && _e !== void 0 ? _e : ''), placeholder: t('filter_search_value', this.locale), onInput: (e) => this.setPending('value', e.target.value) }))));
610
752
  }
611
753
  if (NUMERIC_TYPES.has(dataType)) {
612
754
  const numOp = pf.operator;
@@ -634,7 +776,7 @@ export class MrdTable {
634
776
  else {
635
777
  this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: undefined });
636
778
  }
637
- } }, h("option", { value: "", selected: !noInput }, t('filter_has_value', this.locale)), h("option", { value: "isEmpty", selected: dtOp === 'isEmpty' }, t('filter_is_empty', this.locale)), h("option", { value: "isNotEmpty", selected: dtOp === 'isNotEmpty' }, t('filter_is_not_empty', this.locale))), !noInput && (h("div", { class: "mrd-table__filter-editor" }, h("div", { class: "mrd-table__filter-radio-group mrd-table__filter-radio-group--inline" }, h("label", { class: "mrd-table__filter-radio-label" }, h("input", { type: "radio", name: `dt-${this.openFilterCol}`, checked: !rangeMode, onChange: () => { this.pendingFilter = Object.assign(Object.assign({}, pf), { from: undefined, to: undefined }); } }), t('filter_exact', this.locale)), h("label", { class: "mrd-table__filter-radio-label" }, h("input", { type: "radio", name: `dt-${this.openFilterCol}`, checked: rangeMode, onChange: () => { this.pendingFilter = Object.assign(Object.assign({}, pf), { value: undefined, from: null, to: null }); } }), t('filter_range', this.locale))), !rangeMode ? (h("input", { type: "date", class: "mrd-table__filter-input", value: String((_g = pf.value) !== null && _g !== void 0 ? _g : ''), onInput: (e) => this.setPending('value', e.target.value) })) : (h("div", { class: "mrd-table__filter-range mrd-table__filter-range--stacked" }, h("label", { class: "mrd-table__filter-range-label" }, t('filter_from', this.locale)), h("input", { type: "date", class: "mrd-table__filter-input", value: pf.from != null ? String(pf.from) : '', onInput: (e) => this.setPending('from', e.target.value) }), h("label", { class: "mrd-table__filter-range-label" }, t('filter_to', this.locale)), h("input", { type: "date", class: "mrd-table__filter-input", value: pf.to != null ? String(pf.to) : '', onInput: (e) => this.setPending('to', e.target.value) })))))));
779
+ } }, h("option", { value: "", selected: !noInput }, t('filter_has_value', this.locale)), h("option", { value: "isEmpty", selected: dtOp === 'isEmpty' }, t('filter_is_empty', this.locale)), h("option", { value: "isNotEmpty", selected: dtOp === 'isNotEmpty' }, t('filter_is_not_empty', this.locale))), !noInput && (h("div", { class: "mrd-table__filter-editor" }, h("div", { class: "mrd-table__filter-radio-group mrd-table__filter-radio-group--inline" }, h("label", { class: "mrd-table__filter-radio-label" }, h("input", { type: "radio", name: `dt-${this.openFilterCol}`, checked: !rangeMode, onChange: () => { this.pendingFilter = Object.assign(Object.assign({}, pf), { from: undefined, to: undefined }); } }), t('filter_exact', this.locale)), h("label", { class: "mrd-table__filter-radio-label" }, h("input", { type: "radio", name: `dt-${this.openFilterCol}`, checked: rangeMode, onChange: () => { this.pendingFilter = Object.assign(Object.assign({}, pf), { value: undefined, from: null, to: null }); } }), t('filter_range', this.locale))), !rangeMode ? (h("input", { type: "date", class: "mrd-table__filter-input", value: String((_f = pf.value) !== null && _f !== void 0 ? _f : ''), onInput: (e) => this.setPending('value', e.target.value) })) : (h("div", { class: "mrd-table__filter-range mrd-table__filter-range--stacked" }, h("label", { class: "mrd-table__filter-range-label" }, t('filter_from', this.locale)), h("input", { type: "date", class: "mrd-table__filter-input", value: pf.from != null ? String(pf.from) : '', onInput: (e) => this.setPending('from', e.target.value) }), h("label", { class: "mrd-table__filter-range-label" }, t('filter_to', this.locale)), h("input", { type: "date", class: "mrd-table__filter-input", value: pf.to != null ? String(pf.to) : '', onInput: (e) => this.setPending('to', e.target.value) })))))));
638
780
  }
639
781
  if (DATE_TYPES.has(dataType)) {
640
782
  const inputType = dataType === 'DATE' ? 'date' : 'time';
@@ -649,18 +791,18 @@ export class MrdTable {
649
791
  else {
650
792
  this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: undefined });
651
793
  }
652
- } }, h("option", { value: "", selected: !noInput }, t('filter_has_value', this.locale)), h("option", { value: "isEmpty", selected: dtdOp === 'isEmpty' }, t('filter_is_empty', this.locale)), h("option", { value: "isNotEmpty", selected: dtdOp === 'isNotEmpty' }, t('filter_is_not_empty', this.locale))), !noInput && (h("div", { class: "mrd-table__filter-editor" }, h("div", { class: "mrd-table__filter-radio-group mrd-table__filter-radio-group--inline" }, h("label", { class: "mrd-table__filter-radio-label" }, h("input", { type: "radio", name: `dt-${this.openFilterCol}`, checked: !rangeMode, onChange: () => { this.pendingFilter = Object.assign(Object.assign({}, pf), { from: undefined, to: undefined }); } }), t('filter_exact', this.locale)), h("label", { class: "mrd-table__filter-radio-label" }, h("input", { type: "radio", name: `dt-${this.openFilterCol}`, checked: rangeMode, onChange: () => { this.pendingFilter = Object.assign(Object.assign({}, pf), { value: undefined, from: null, to: null }); } }), t('filter_range', this.locale))), !rangeMode ? (h("input", { type: inputType, class: "mrd-table__filter-input", value: String((_h = pf.value) !== null && _h !== void 0 ? _h : ''), onInput: (e) => this.setPending('value', e.target.value) })) : (h("div", { class: "mrd-table__filter-range" }, h("input", { type: inputType, class: "mrd-table__filter-input", placeholder: t('filter_from', this.locale), value: pf.from != null ? String(pf.from) : '', onInput: (e) => this.setPending('from', e.target.value) }), h("input", { type: inputType, class: "mrd-table__filter-input", placeholder: t('filter_to', this.locale), value: pf.to != null ? String(pf.to) : '', onInput: (e) => this.setPending('to', e.target.value) })))))));
794
+ } }, h("option", { value: "", selected: !noInput }, t('filter_has_value', this.locale)), h("option", { value: "isEmpty", selected: dtdOp === 'isEmpty' }, t('filter_is_empty', this.locale)), h("option", { value: "isNotEmpty", selected: dtdOp === 'isNotEmpty' }, t('filter_is_not_empty', this.locale))), !noInput && (h("div", { class: "mrd-table__filter-editor" }, h("div", { class: "mrd-table__filter-radio-group mrd-table__filter-radio-group--inline" }, h("label", { class: "mrd-table__filter-radio-label" }, h("input", { type: "radio", name: `dt-${this.openFilterCol}`, checked: !rangeMode, onChange: () => { this.pendingFilter = Object.assign(Object.assign({}, pf), { from: undefined, to: undefined }); } }), t('filter_exact', this.locale)), h("label", { class: "mrd-table__filter-radio-label" }, h("input", { type: "radio", name: `dt-${this.openFilterCol}`, checked: rangeMode, onChange: () => { this.pendingFilter = Object.assign(Object.assign({}, pf), { value: undefined, from: null, to: null }); } }), t('filter_range', this.locale))), !rangeMode ? (h("input", { type: inputType, class: "mrd-table__filter-input", value: String((_g = pf.value) !== null && _g !== void 0 ? _g : ''), onInput: (e) => this.setPending('value', e.target.value) })) : (h("div", { class: "mrd-table__filter-range" }, h("input", { type: inputType, class: "mrd-table__filter-input", placeholder: t('filter_from', this.locale), value: pf.from != null ? String(pf.from) : '', onInput: (e) => this.setPending('from', e.target.value) }), h("input", { type: inputType, class: "mrd-table__filter-input", placeholder: t('filter_to', this.locale), value: pf.to != null ? String(pf.to) : '', onInput: (e) => this.setPending('to', e.target.value) })))))));
653
795
  }
654
796
  return null;
655
797
  }
656
798
  renderFilterPopup() {
657
- var _a, _b, _c, _d;
799
+ var _a;
658
800
  if (!this.openFilterCol || !this.pendingFilter)
659
801
  return null;
660
802
  const col = this.columns.find(c => this.colName(c) === this.openFilterCol);
661
803
  if (!col)
662
804
  return null;
663
- const label = (_d = (_b = (_a = col.field) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : (_c = col.relation) === null || _c === void 0 ? void 0 : _c.label) !== null && _d !== void 0 ? _d : this.openFilterCol;
805
+ const label = (_a = col.label) !== null && _a !== void 0 ? _a : this.openFilterCol;
664
806
  const sortActive = this.sortField === this.openFilterCol;
665
807
  return (h("div", { class: "mrd-table__filter-popup", style: { top: `${this.popupPos.top}px`, left: `${this.popupPos.left}px` }, onClick: (e) => e.stopPropagation() }, h("div", { class: "mrd-table__filter-popup-header" }, h("span", { class: "mrd-table__filter-popup-title" }, label), h("button", { class: "mrd-table__filter-close", onClick: () => this.closeFilterPopup() }, "\u2715")), h("div", { class: "mrd-table__filter-section" }, h("div", { class: "mrd-table__filter-section-label" }, t('filter_sorting', this.locale)), h("div", { class: "mrd-table__filter-sort-buttons" }, h("button", { class: `mrd-table__filter-sort-btn${sortActive && this.sortDir === 'asc' ? ' mrd-table__filter-sort-btn--active' : ''}`, onClick: () => this.applySort(col, 'asc') }, "\u25B2 ", t('filter_ascending', this.locale)), h("button", { class: `mrd-table__filter-sort-btn${sortActive && this.sortDir === 'desc' ? ' mrd-table__filter-sort-btn--active' : ''}`, onClick: () => this.applySort(col, 'desc') }, "\u25BC ", t('filter_descending', this.locale)))), h("div", { class: "mrd-table__filter-divider" }), h("div", { class: "mrd-table__filter-section" }, h("div", { class: "mrd-table__filter-section-label" }, t('filter_section', this.locale)), this.renderFilterEditor(col)), h("div", { class: "mrd-table__filter-popup-footer" }, h("button", { class: "mrd-table__filter-btn mrd-table__filter-btn--clear", onClick: () => this.clearFilter() }, t('filter_clear', this.locale)), h("button", { class: "mrd-table__filter-btn mrd-table__filter-btn--apply", onClick: () => this.applyFilter() }, t('filter_apply', this.locale)))));
666
808
  }
@@ -687,13 +829,13 @@ export class MrdTable {
687
829
  }
688
830
  // ── Render: cell ──────────────────────────────────────────────────────────
689
831
  renderCell(col, row) {
690
- var _a, _b, _c, _d, _e, _f;
832
+ var _a, _b, _c;
691
833
  const numericTypes = new Set(['INTEGER', 'DECIMAL', 'PERCENTAGE', 'CURRENCY']);
692
- const dataType = (_b = (_a = col.field) === null || _a === void 0 ? void 0 : _a.dataType) !== null && _b !== void 0 ? _b : '';
834
+ const dataType = (_a = col.dataType) !== null && _a !== void 0 ? _a : '';
693
835
  const isNumeric = col.type === 'FIELD' && numericTypes.has(dataType);
694
836
  const isFile = col.type === 'FIELD' && (dataType === 'FILE' || dataType === 'IMAGE');
695
837
  if (isFile) {
696
- const name = (_d = (_c = col.field) === null || _c === void 0 ? void 0 : _c.name) !== null && _d !== void 0 ? _d : '';
838
+ const name = (_b = col.name) !== null && _b !== void 0 ? _b : '';
697
839
  const fileVal = row === null || row === void 0 ? void 0 : row[name];
698
840
  const href = fileVal === null || fileVal === void 0 ? void 0 : fileVal.href;
699
841
  const fileName = fileVal === null || fileVal === void 0 ? void 0 : fileVal.fileName;
@@ -703,7 +845,7 @@ export class MrdTable {
703
845
  } }, h("svg", { class: "mrd-table__file-icon", viewBox: "0 0 24 24", "aria-hidden": "true" }, h("path", { fill: "currentColor", d: "M14 2H6c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h12c1.1 0 2-.9 2-2V8l-6-6zm-1 7V3.5L18.5 9H13zm-3 8l-3-3 1.41-1.41L10 14.17l4.59-4.58L16 11l-6 6z" })), t('download', this.locale))) : ''));
704
846
  }
705
847
  if (dataType === 'JSON') {
706
- const name = (_f = (_e = col.field) === null || _e === void 0 ? void 0 : _e.name) !== null && _f !== void 0 ? _f : '';
848
+ const name = (_c = col.name) !== null && _c !== void 0 ? _c : '';
707
849
  const rawValue = name ? row === null || row === void 0 ? void 0 : row[name] : undefined;
708
850
  if (rawValue == null || rawValue === '')
709
851
  return h("td", { class: "mrd-table__cell" });
@@ -727,12 +869,12 @@ export class MrdTable {
727
869
  renderTotalsRow() {
728
870
  if (!this.aggregations)
729
871
  return null;
730
- if (!this.columns.some(c => { var _a; return c.type === 'FIELD' && ((_a = c.field) === null || _a === void 0 ? void 0 : _a.aggregate); }))
872
+ if (!this.columns.some(c => c.type === 'FIELD' && c.aggregate))
731
873
  return null;
732
874
  return (h("tfoot", null, h("tr", { class: "mrd-table__totals-row" }, this.columns.map(col => {
733
- var _a, _b;
875
+ var _a;
734
876
  const val = this.renderAggregationValue(col);
735
- const isNumeric = col.type === 'FIELD' && NUMERIC_TYPES.has((_b = (_a = col.field) === null || _a === void 0 ? void 0 : _a.dataType) !== null && _b !== void 0 ? _b : '');
877
+ const isNumeric = col.type === 'FIELD' && NUMERIC_TYPES.has((_a = col.dataType) !== null && _a !== void 0 ? _a : '');
736
878
  return (h("td", { class: `mrd-table__totals-cell${isNumeric ? ' mrd-table__totals-cell--numeric' : ''}` }, val));
737
879
  }))));
738
880
  }
@@ -744,7 +886,7 @@ export class MrdTable {
744
886
  // ── Non-paginated mode ──────────────────────────────────────────────────
745
887
  if (this.totalElements === 0) {
746
888
  return (h(Host, null, this.renderToolbar(), h("div", { class: "mrd-table" }, h("table", { class: "mrd-table__table" }, h("thead", null, h("tr", null, this.columns.map(col => {
747
- var _a, _b, _c, _d;
889
+ var _a;
748
890
  const name = this.colName(col);
749
891
  const isFiltered = this.activeFilters.has(name);
750
892
  const cls = [
@@ -752,7 +894,7 @@ export class MrdTable {
752
894
  isFiltered ? 'mrd-table__header--filtered' : '',
753
895
  this.filterMode ? 'mrd-table__header--sortable' : '',
754
896
  ].filter(Boolean).join(' ');
755
- return (h("th", { class: cls, onClick: this.filterMode ? (e) => this.handleFilterOpen(col, e) : undefined }, h("span", { class: "mrd-table__header-label" }, (_d = (_b = (_a = col.field) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : (_c = col.relation) === null || _c === void 0 ? void 0 : _c.label) !== null && _d !== void 0 ? _d : ''), isFiltered && this.renderFilterIcon()));
897
+ return (h("th", { class: cls, onClick: this.filterMode ? (e) => this.handleFilterOpen(col, e) : undefined }, h("span", { class: "mrd-table__header-label" }, (_a = col.label) !== null && _a !== void 0 ? _a : ''), isFiltered && this.renderFilterIcon()));
756
898
  }))), h("tbody", null, (_b = this.rows) === null || _b === void 0 ? void 0 : _b.map((row, i) => (h("tr", { class: "mrd-table__row mrd-table__row--clickable", style: { background: i % 2 === 0 ? '' : 'var(--mrd-color-neutral-100)' }, onClick: () => this.mrdRowClick.emit(row) }, this.columns.map(col => this.renderCell(col, row)))))), this.renderTotalsRow()), (!this.rows || this.rows.length === 0) && (h("p", { class: "mrd-table__empty" }, t('no_results', this.locale)))), this.renderFooter((_c = this.rows) === null || _c === void 0 ? void 0 : _c.length), this.renderFilterPopup(), this.renderTextblockModal(), this.renderJsonModal()));
757
899
  }
758
900
  // ── Paginated / virtual-scroll mode ────────────────────────────────────
@@ -785,7 +927,7 @@ export class MrdTable {
785
927
  }
786
928
  }
787
929
  return (h(Host, null, this.renderToolbar(), h("div", { class: "mrd-table__scroll", style: { height: `${this.tableHeight}px` }, onScroll: this.handleScroll }, h("table", { class: "mrd-table__table", style: tableStyle }, h("thead", null, h("tr", null, this.columns.map((col, idx) => {
788
- var _a, _b, _c, _d;
930
+ var _a;
789
931
  const name = this.colName(col);
790
932
  const isActive = this.sortField === name;
791
933
  const isFiltered = this.activeFilters.has(name);
@@ -796,7 +938,7 @@ export class MrdTable {
796
938
  isActive ? `mrd-table__header--sorted-${this.sortDir}` : '',
797
939
  isFiltered ? 'mrd-table__header--filtered' : '',
798
940
  ].filter(Boolean).join(' ');
799
- return (h("th", { class: cls, style: this.colWidths[idx] ? { width: `${this.colWidths[idx]}px` } : undefined, onClick: isInteractive ? ((e) => this.filterMode ? this.handleFilterOpen(col, e) : this.handleSortClick(col)) : undefined }, h("span", { class: "mrd-table__header-label" }, (_d = (_b = (_a = col.field) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : (_c = col.relation) === null || _c === void 0 ? void 0 : _c.label) !== null && _d !== void 0 ? _d : ''), isInteractive && isActive && (h("span", { class: "mrd-table__sort-icon", "aria-hidden": "true" }, this.sortDir === 'asc' ? '▲' : '▼')), isInteractive && !isActive && !this.filterMode && (h("span", { class: "mrd-table__sort-icon", "aria-hidden": "true" }, "\u21C5")), isInteractive && isFiltered && this.renderFilterIcon()));
941
+ return (h("th", { class: cls, style: this.colWidths[idx] ? { width: `${this.colWidths[idx]}px` } : undefined, onClick: isInteractive ? ((e) => this.filterMode ? this.handleFilterOpen(col, e) : this.handleSortClick(col)) : undefined }, h("span", { class: "mrd-table__header-label" }, (_a = col.label) !== null && _a !== void 0 ? _a : ''), isInteractive && isActive && (h("span", { class: "mrd-table__sort-icon", "aria-hidden": "true" }, this.sortDir === 'asc' ? '▲' : '▼')), isInteractive && !isActive && !this.filterMode && (h("span", { class: "mrd-table__sort-icon", "aria-hidden": "true" }, "\u21C5")), isInteractive && isFiltered && this.renderFilterIcon()));
800
942
  }))), h("tbody", null, topSpacerHeight > 0 && (h("tr", { class: "mrd-table__spacer", style: { height: `${topSpacerHeight}px` } }, h("td", { colSpan: colCount }))), renderedRows, bottomSpacerHeight > 0 && (h("tr", { class: "mrd-table__spacer", style: { height: `${bottomSpacerHeight}px` } }, h("td", { colSpan: colCount })))), this.renderTotalsRow())), effectiveTotal === 0 && this.loadedPages.has(0) && (h("p", { class: "mrd-table__empty" }, t('no_results', this.locale))), effectiveTotal > 0 && this.renderFooter(undefined, effectiveTotal), this.renderFilterPopup(), this.renderTextblockModal()));
801
943
  }
802
944
  renderFilterIcon() {
@@ -826,18 +968,18 @@ export class MrdTable {
826
968
  }
827
969
  static get properties() {
828
970
  return {
829
- "columns": {
971
+ "item": {
830
972
  "type": "unknown",
831
973
  "mutable": false,
832
974
  "complexType": {
833
- "original": "TableColumn[]",
834
- "resolved": "ClientLayoutItem[]",
975
+ "original": "ClientLayoutItem | null",
976
+ "resolved": "ClientLayoutItem | null",
835
977
  "references": {
836
- "TableColumn": {
978
+ "ClientLayoutItem": {
837
979
  "location": "import",
838
- "path": "../../utils/cell-renderer",
839
- "id": "src/utils/cell-renderer.ts::TableColumn",
840
- "referenceLocation": "TableColumn"
980
+ "path": "../../types/client-layout",
981
+ "id": "src/types/client-layout.ts::ClientLayoutItem",
982
+ "referenceLocation": "ClientLayoutItem"
841
983
  }
842
984
  }
843
985
  },
@@ -845,11 +987,31 @@ export class MrdTable {
845
987
  "optional": false,
846
988
  "docs": {
847
989
  "tags": [],
848
- "text": ""
990
+ "text": "The VIEW or RELATED_VIEW layout item. Contains view config, dataClass, fromClass, actions etc."
849
991
  },
850
992
  "getter": false,
851
993
  "setter": false,
852
- "defaultValue": "[]"
994
+ "defaultValue": "null"
995
+ },
996
+ "parentId": {
997
+ "type": "string",
998
+ "mutable": false,
999
+ "complexType": {
1000
+ "original": "string",
1001
+ "resolved": "string",
1002
+ "references": {}
1003
+ },
1004
+ "required": false,
1005
+ "optional": false,
1006
+ "docs": {
1007
+ "tags": [],
1008
+ "text": "Parent record id \u2014 required for RELATED_VIEW to build /{fromClass}/{parentId}/{dataClass}."
1009
+ },
1010
+ "getter": false,
1011
+ "setter": false,
1012
+ "reflect": false,
1013
+ "attribute": "parent-id",
1014
+ "defaultValue": "''"
853
1015
  },
854
1016
  "rows": {
855
1017
  "type": "unknown",
@@ -973,101 +1135,12 @@ export class MrdTable {
973
1135
  "reflect": false,
974
1136
  "attribute": "table-height",
975
1137
  "defaultValue": "500"
976
- },
977
- "defaultSort": {
978
- "type": "string",
979
- "mutable": false,
980
- "complexType": {
981
- "original": "string",
982
- "resolved": "string",
983
- "references": {}
984
- },
985
- "required": false,
986
- "optional": false,
987
- "docs": {
988
- "tags": [],
989
- "text": "Initial sort applied on load, e.g. \"timestamp,desc\" or \"name\".\nParsed by init() into sortField + sortDir."
990
- },
991
- "getter": false,
992
- "setter": false,
993
- "reflect": false,
994
- "attribute": "default-sort",
995
- "defaultValue": "''"
996
- },
997
- "actions": {
998
- "type": "unknown",
999
- "mutable": false,
1000
- "complexType": {
1001
- "original": "TableAction[]",
1002
- "resolved": "TableAction[]",
1003
- "references": {
1004
- "TableAction": {
1005
- "location": "import",
1006
- "path": "../../utils/cell-renderer",
1007
- "id": "src/utils/cell-renderer.ts::TableAction",
1008
- "referenceLocation": "TableAction"
1009
- }
1010
- }
1011
- },
1012
- "required": false,
1013
- "optional": false,
1014
- "docs": {
1015
- "tags": [],
1016
- "text": "Toolbar action buttons rendered above the table."
1017
- },
1018
- "getter": false,
1019
- "setter": false,
1020
- "defaultValue": "[]"
1021
- },
1022
- "viewLabel": {
1023
- "type": "string",
1024
- "mutable": false,
1025
- "complexType": {
1026
- "original": "string",
1027
- "resolved": "string",
1028
- "references": {}
1029
- },
1030
- "required": false,
1031
- "optional": false,
1032
- "docs": {
1033
- "tags": [],
1034
- "text": "Display label of the current view \u2014 shown in the toolbar center as a view picker trigger."
1035
- },
1036
- "getter": false,
1037
- "setter": false,
1038
- "reflect": false,
1039
- "attribute": "view-label",
1040
- "defaultValue": "''"
1041
- },
1042
- "alternativeViews": {
1043
- "type": "unknown",
1044
- "mutable": false,
1045
- "complexType": {
1046
- "original": "AlternativeView[]",
1047
- "resolved": "AlternativeView[]",
1048
- "references": {
1049
- "AlternativeView": {
1050
- "location": "import",
1051
- "path": "../../utils/cell-renderer",
1052
- "id": "src/utils/cell-renderer.ts::AlternativeView",
1053
- "referenceLocation": "AlternativeView"
1054
- }
1055
- }
1056
- },
1057
- "required": false,
1058
- "optional": false,
1059
- "docs": {
1060
- "tags": [],
1061
- "text": "Alternative views available for this table; renders a dropdown when non-empty."
1062
- },
1063
- "getter": false,
1064
- "setter": false,
1065
- "defaultValue": "[]"
1066
1138
  }
1067
1139
  };
1068
1140
  }
1069
1141
  static get states() {
1070
1142
  return {
1143
+ "activeViewIdx": {},
1071
1144
  "loadedPages": {},
1072
1145
  "requestedPages": {},
1073
1146
  "renderStart": {},
@@ -1098,8 +1171,8 @@ export class MrdTable {
1098
1171
  "text": "Fired when a page needs to be fetched. Host fetches and calls setPage().\n`sort` is the raw query-param value, e.g. \"name\" or \"name,desc\"."
1099
1172
  },
1100
1173
  "complexType": {
1101
- "original": "{ page: number; sort: string }",
1102
- "resolved": "{ page: number; sort: string; }",
1174
+ "original": "{ page: number; sort: string; path: string; qs: string }",
1175
+ "resolved": "{ page: number; sort: string; path: string; qs: string; }",
1103
1176
  "references": {}
1104
1177
  }
1105
1178
  }, {
@@ -1130,35 +1203,13 @@ export class MrdTable {
1130
1203
  "composed": true,
1131
1204
  "docs": {
1132
1205
  "tags": [],
1133
- "text": "Fired when a toolbar action button is clicked. Detail contains the action identifier."
1206
+ "text": "Fired when a toolbar action button is clicked.\nFor 'export': includes `path` (relative excel path) and `qs` (current sort+filter params).\nFor 'create': includes `dataClass` (target type) and `parentPath` (e.g. /buyers/123 for RELATED_VIEW)."
1134
1207
  },
1135
1208
  "complexType": {
1136
- "original": "{ action: string }",
1137
- "resolved": "{ action: string; }",
1209
+ "original": "{ action: string; path?: string; qs?: string; dataClass?: string; parentPath?: string | null }",
1210
+ "resolved": "{ action: string; path?: string | undefined; qs?: string | undefined; dataClass?: string | undefined; parentPath?: string | null | undefined; }",
1138
1211
  "references": {}
1139
1212
  }
1140
- }, {
1141
- "method": "mrdFilter",
1142
- "name": "mrdFilter",
1143
- "bubbles": true,
1144
- "cancelable": true,
1145
- "composed": true,
1146
- "docs": {
1147
- "tags": [],
1148
- "text": "Fired when active filters change. Host translates filters to API query params."
1149
- },
1150
- "complexType": {
1151
- "original": "{ filters: ColumnFilter[] }",
1152
- "resolved": "{ filters: ColumnFilter[]; }",
1153
- "references": {
1154
- "ColumnFilter": {
1155
- "location": "import",
1156
- "path": "../../utils/cell-renderer",
1157
- "id": "src/utils/cell-renderer.ts::ColumnFilter",
1158
- "referenceLocation": "ColumnFilter"
1159
- }
1160
- }
1161
- }
1162
1213
  }, {
1163
1214
  "method": "mrdDownload",
1164
1215
  "name": "mrdDownload",
@@ -1174,21 +1225,6 @@ export class MrdTable {
1174
1225
  "resolved": "{ href: string; fileName: string; }",
1175
1226
  "references": {}
1176
1227
  }
1177
- }, {
1178
- "method": "mrdSwitchView",
1179
- "name": "mrdSwitchView",
1180
- "bubbles": true,
1181
- "cancelable": true,
1182
- "composed": true,
1183
- "docs": {
1184
- "tags": [],
1185
- "text": "Fired when the user selects an alternative view from the view switcher dropdown."
1186
- },
1187
- "complexType": {
1188
- "original": "{ name: string; class?: string }",
1189
- "resolved": "{ name: string; class?: string | undefined; }",
1190
- "references": {}
1191
- }
1192
1228
  }, {
1193
1229
  "method": "mrdLoadAggregations",
1194
1230
  "name": "mrdLoadAggregations",
@@ -1200,8 +1236,8 @@ export class MrdTable {
1200
1236
  "text": "Fired when aggregation totals need to be (re-)fetched.\nDetail contains the fields grouped by aggregate function.\nHost calls the /aggregations endpoint and passes the result to setAggregations()."
1201
1237
  },
1202
1238
  "complexType": {
1203
- "original": "{ sum?: string[]; avg?: string[]; count?: string[] }",
1204
- "resolved": "{ sum?: string[] | undefined; avg?: string[] | undefined; count?: string[] | undefined; }",
1239
+ "original": "{ sum?: string[]; avg?: string[]; count?: string[]; path: string; qs: string }",
1240
+ "resolved": "{ sum?: string[] | undefined; avg?: string[] | undefined; count?: string[] | undefined; path: string; qs: string; }",
1205
1241
  "references": {}
1206
1242
  }
1207
1243
  }];
@@ -1293,8 +1329,8 @@ export class MrdTable {
1293
1329
  "propName": "totalElements",
1294
1330
  "methodName": "totalElementsChanged"
1295
1331
  }, {
1296
- "propName": "defaultSort",
1297
- "methodName": "defaultSortChanged"
1332
+ "propName": "item",
1333
+ "methodName": "itemChanged"
1298
1334
  }];
1299
1335
  }
1300
1336
  }