@mmlogic/components 0.3.10 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/dist/cjs/{index-BPj2cBXs.js → index-CAzwGt9u.js} +38 -0
  2. package/dist/cjs/loader.cjs.js +2 -2
  3. package/dist/cjs/mosterdcomponents.cjs.js +2 -2
  4. package/dist/cjs/mrd-boolean-field_23.cjs.entry.js +1280 -1073
  5. package/dist/collection/collection-manifest.json +23 -23
  6. package/dist/collection/components/{mrd-document-container/mrd-document-container.scss → documents/mrd-document-container/mrd-document-container.css} +3 -3
  7. package/dist/collection/components/{mrd-document-container → documents/mrd-document-container}/mrd-document-container.js +54 -8
  8. package/dist/collection/components/documents/mrd-document-list/folder-tree.js +109 -0
  9. package/dist/collection/components/{mrd-document-list/mrd-document-list.scss → documents/mrd-document-list/mrd-document-list.css} +17 -4
  10. package/dist/collection/components/{mrd-document-list → documents/mrd-document-list}/mrd-document-list.js +166 -237
  11. package/dist/collection/components/documents/mrd-document-list/tree-view.js +75 -0
  12. package/dist/collection/components/{mrd-document-view/mrd-document-view.scss → documents/mrd-document-view/mrd-document-view.css} +1 -1
  13. package/dist/collection/components/{mrd-document-view → documents/mrd-document-view}/mrd-document-view.js +4 -4
  14. package/dist/collection/components/fields/field-helpers.js +17 -0
  15. package/dist/collection/components/fields/file-upload-common.js +38 -0
  16. package/dist/collection/components/{mrd-boolean-field/mrd-boolean-field.scss → fields/mrd-boolean-field/mrd-boolean-field.css} +3 -3
  17. package/dist/collection/components/{mrd-boolean-field → fields/mrd-boolean-field}/mrd-boolean-field.js +1 -1
  18. package/dist/collection/components/{mrd-currency-field/mrd-currency-field.scss → fields/mrd-currency-field/mrd-currency-field.css} +11 -9
  19. package/dist/collection/components/{mrd-currency-field → fields/mrd-currency-field}/mrd-currency-field.js +7 -13
  20. package/dist/collection/components/{mrd-date-field/mrd-date-field.scss → fields/mrd-date-field/mrd-date-field.css} +8 -10
  21. package/dist/collection/components/{mrd-date-field → fields/mrd-date-field}/mrd-date-field.js +3 -10
  22. package/dist/collection/components/{mrd-datetime-field/mrd-datetime-field.scss → fields/mrd-datetime-field/mrd-datetime-field.css} +8 -10
  23. package/dist/collection/components/{mrd-datetime-field → fields/mrd-datetime-field}/mrd-datetime-field.js +3 -10
  24. package/dist/collection/components/{mrd-email-field/mrd-email-field.scss → fields/mrd-email-field/mrd-email-field.css} +2 -11
  25. package/dist/collection/components/{mrd-email-field → fields/mrd-email-field}/mrd-email-field.js +6 -13
  26. package/dist/collection/components/{mrd-file-field/mrd-file-field.scss → fields/mrd-file-field/mrd-file-field.css} +19 -24
  27. package/dist/collection/components/{mrd-file-field → fields/mrd-file-field}/mrd-file-field.js +13 -24
  28. package/dist/collection/components/{mrd-hyperlink-field/mrd-hyperlink-field.scss → fields/mrd-hyperlink-field/mrd-hyperlink-field.css} +7 -16
  29. package/dist/collection/components/{mrd-hyperlink-field → fields/mrd-hyperlink-field}/mrd-hyperlink-field.js +9 -15
  30. package/dist/collection/components/{mrd-image-field/mrd-image-field.scss → fields/mrd-image-field/mrd-image-field.css} +15 -24
  31. package/dist/collection/components/{mrd-image-field → fields/mrd-image-field}/mrd-image-field.js +13 -28
  32. package/dist/collection/components/{mrd-list-field/mrd-list-field.scss → fields/mrd-list-field/mrd-list-field.css} +18 -21
  33. package/dist/collection/components/{mrd-list-field → fields/mrd-list-field}/mrd-list-field.js +10 -25
  34. package/dist/collection/components/{mrd-longtext-field/mrd-longtext-field.scss → fields/mrd-longtext-field/mrd-longtext-field.css} +21 -18
  35. package/dist/collection/components/{mrd-longtext-field → fields/mrd-longtext-field}/mrd-longtext-field.js +3 -10
  36. package/dist/collection/components/{mrd-number-field/mrd-number-field.scss → fields/mrd-number-field/mrd-number-field.css} +9 -10
  37. package/dist/collection/components/{mrd-number-field → fields/mrd-number-field}/mrd-number-field.js +7 -6
  38. package/dist/collection/components/{mrd-relation-field/mrd-relation-field.scss → fields/mrd-relation-field/mrd-relation-field.css} +61 -59
  39. package/dist/collection/components/{mrd-relation-field → fields/mrd-relation-field}/mrd-relation-field.js +16 -26
  40. package/dist/collection/components/{mrd-secret-field/mrd-secret-field.scss → fields/mrd-secret-field/mrd-secret-field.css} +7 -10
  41. package/dist/collection/components/{mrd-secret-field → fields/mrd-secret-field}/mrd-secret-field.js +4 -11
  42. package/dist/collection/components/{mrd-text-field/mrd-text-field.scss → fields/mrd-text-field/mrd-text-field.css} +2 -11
  43. package/dist/collection/components/{mrd-text-field → fields/mrd-text-field}/mrd-text-field.js +3 -10
  44. package/dist/collection/components/{mrd-textarea-field/mrd-textarea-field.scss → fields/mrd-textarea-field/mrd-textarea-field.css} +7 -10
  45. package/dist/collection/components/{mrd-textarea-field → fields/mrd-textarea-field}/mrd-textarea-field.js +3 -9
  46. package/dist/collection/components/{mrd-time-field/mrd-time-field.scss → fields/mrd-time-field/mrd-time-field.css} +8 -10
  47. package/dist/collection/components/{mrd-time-field → fields/mrd-time-field}/mrd-time-field.js +3 -10
  48. package/dist/collection/components/{mrd-field/mrd-field.scss → form/mrd-field/mrd-field.css} +1 -1
  49. package/dist/collection/components/{mrd-field → form/mrd-field}/mrd-field.js +3 -3
  50. package/dist/collection/components/{mrd-form/mrd-form.scss → form/mrd-form/mrd-form.css} +1 -1
  51. package/dist/collection/components/{mrd-form → form/mrd-form}/mrd-form.js +5 -5
  52. package/dist/collection/components/layout/mrd-layout-section/field-value.js +111 -0
  53. package/dist/collection/components/layout/mrd-layout-section/layout-helpers.js +29 -0
  54. package/dist/collection/components/{mrd-layout-section/mrd-layout-section.scss → layout/mrd-layout-section/mrd-layout-section.css} +4 -4
  55. package/dist/collection/components/{mrd-layout-section → layout/mrd-layout-section}/mrd-layout-section.js +58 -133
  56. package/dist/collection/components/{mrd-table/mrd-table.scss → table/mrd-table/mrd-table.css} +11 -13
  57. package/dist/collection/components/{mrd-table → table/mrd-table}/mrd-table.js +111 -439
  58. package/dist/collection/components/table/mrd-table/table-filter-popup.js +85 -0
  59. package/dist/collection/components/table/mrd-table/table-parts.js +110 -0
  60. package/dist/collection/components/table/mrd-table/table-query.js +178 -0
  61. package/dist/collection/components/table/mrd-table/virtual-scroll.js +49 -0
  62. package/dist/collection/dev/app.js +19 -18
  63. package/dist/collection/dev/example-data.js +58 -43
  64. package/dist/collection/utils/i18n.js +10 -0
  65. package/dist/collection/utils/query-params.js +43 -0
  66. package/dist/components/field-helpers.js +1 -0
  67. package/dist/components/file-upload-common.js +1 -0
  68. package/dist/components/i18n.js +1 -1
  69. package/dist/components/mrd-boolean-field2.js +1 -1
  70. package/dist/components/mrd-currency-field2.js +1 -1
  71. package/dist/components/mrd-date-field2.js +1 -1
  72. package/dist/components/mrd-datetime-field2.js +1 -1
  73. package/dist/components/mrd-document-container2.js +1 -1
  74. package/dist/components/mrd-document-list2.js +1 -1
  75. package/dist/components/mrd-document-view2.js +1 -1
  76. package/dist/components/mrd-email-field2.js +1 -1
  77. package/dist/components/mrd-file-field2.js +1 -1
  78. package/dist/components/mrd-form.js +1 -1
  79. package/dist/components/mrd-hyperlink-field2.js +1 -1
  80. package/dist/components/mrd-image-field2.js +1 -1
  81. package/dist/components/mrd-layout-section.js +1 -1
  82. package/dist/components/mrd-list-field2.js +1 -1
  83. package/dist/components/mrd-longtext-field2.js +1 -1
  84. package/dist/components/mrd-number-field2.js +1 -1
  85. package/dist/components/mrd-relation-field2.js +1 -1
  86. package/dist/components/mrd-secret-field2.js +1 -1
  87. package/dist/components/mrd-table2.js +1 -1
  88. package/dist/components/mrd-text-field2.js +1 -1
  89. package/dist/components/mrd-textarea-field2.js +1 -1
  90. package/dist/components/mrd-time-field2.js +1 -1
  91. package/dist/components/query-params.js +1 -0
  92. package/dist/esm/{index-_tsCCkAi.js → index-DiSEJMA8.js} +38 -1
  93. package/dist/esm/loader.js +3 -3
  94. package/dist/esm/mosterdcomponents.js +3 -3
  95. package/dist/esm/mrd-boolean-field_23.entry.js +1280 -1073
  96. package/dist/mosterdcomponents/mosterdcomponents.css +1 -1
  97. package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
  98. package/dist/mosterdcomponents/p-9b3c0917.entry.js +1 -0
  99. package/dist/mosterdcomponents/p-DiSEJMA8.js +2 -0
  100. package/dist/types/components/{mrd-document-container → documents/mrd-document-container}/mrd-document-container.d.ts +7 -2
  101. package/dist/types/components/documents/mrd-document-list/folder-tree.d.ts +66 -0
  102. package/dist/types/components/{mrd-document-list → documents/mrd-document-list}/mrd-document-list.d.ts +28 -38
  103. package/dist/types/components/documents/mrd-document-list/tree-view.d.ts +32 -0
  104. package/dist/types/components/{mrd-document-view → documents/mrd-document-view}/mrd-document-view.d.ts +2 -2
  105. package/dist/types/components/fields/field-helpers.d.ts +18 -0
  106. package/dist/types/components/fields/file-upload-common.d.ts +18 -0
  107. package/dist/types/components/{mrd-boolean-field → fields/mrd-boolean-field}/mrd-boolean-field.d.ts +1 -1
  108. package/dist/types/components/{mrd-currency-field → fields/mrd-currency-field}/mrd-currency-field.d.ts +2 -2
  109. package/dist/types/components/{mrd-date-field → fields/mrd-date-field}/mrd-date-field.d.ts +1 -1
  110. package/dist/types/components/{mrd-datetime-field → fields/mrd-datetime-field}/mrd-datetime-field.d.ts +1 -1
  111. package/dist/types/components/{mrd-email-field → fields/mrd-email-field}/mrd-email-field.d.ts +1 -1
  112. package/dist/types/components/{mrd-file-field → fields/mrd-file-field}/mrd-file-field.d.ts +2 -4
  113. package/dist/types/components/{mrd-hyperlink-field → fields/mrd-hyperlink-field}/mrd-hyperlink-field.d.ts +2 -2
  114. package/dist/types/components/{mrd-image-field → fields/mrd-image-field}/mrd-image-field.d.ts +2 -4
  115. package/dist/types/components/{mrd-list-field → fields/mrd-list-field}/mrd-list-field.d.ts +2 -2
  116. package/dist/types/components/{mrd-longtext-field → fields/mrd-longtext-field}/mrd-longtext-field.d.ts +1 -1
  117. package/dist/types/components/{mrd-number-field → fields/mrd-number-field}/mrd-number-field.d.ts +2 -2
  118. package/dist/types/components/{mrd-relation-field → fields/mrd-relation-field}/mrd-relation-field.d.ts +2 -2
  119. package/dist/types/components/{mrd-secret-field → fields/mrd-secret-field}/mrd-secret-field.d.ts +1 -1
  120. package/dist/types/components/{mrd-text-field → fields/mrd-text-field}/mrd-text-field.d.ts +1 -1
  121. package/dist/types/components/{mrd-textarea-field → fields/mrd-textarea-field}/mrd-textarea-field.d.ts +1 -1
  122. package/dist/types/components/{mrd-time-field → fields/mrd-time-field}/mrd-time-field.d.ts +1 -1
  123. package/dist/types/components/{mrd-field → form/mrd-field}/mrd-field.d.ts +2 -2
  124. package/dist/types/components/{mrd-form → form/mrd-form}/mrd-form.d.ts +2 -2
  125. package/dist/types/components/layout/mrd-layout-section/field-value.d.ts +22 -0
  126. package/dist/types/components/layout/mrd-layout-section/layout-helpers.d.ts +8 -0
  127. package/dist/types/components/{mrd-layout-section → layout/mrd-layout-section}/mrd-layout-section.d.ts +4 -8
  128. package/dist/types/components/{mrd-table → table/mrd-table}/mrd-table.d.ts +6 -13
  129. package/dist/types/components/table/mrd-table/table-filter-popup.d.ts +35 -0
  130. package/dist/types/components/table/mrd-table/table-parts.d.ts +61 -0
  131. package/dist/types/components/table/mrd-table/table-query.d.ts +50 -0
  132. package/dist/types/components/table/mrd-table/virtual-scroll.d.ts +26 -0
  133. package/dist/types/components.d.ts +36 -5
  134. package/dist/types/types/client-layout.d.ts +5 -0
  135. package/dist/types/utils/query-params.d.ts +14 -0
  136. package/package.json +7 -2
  137. package/dist/components/validation.js +0 -1
  138. package/dist/mosterdcomponents/cell-renderer-B-AJDBcj.js.map +0 -1
  139. package/dist/mosterdcomponents/client-layout-ChqRA3AF.js.map +0 -1
  140. package/dist/mosterdcomponents/format-BAfsQfy1.js.map +0 -1
  141. package/dist/mosterdcomponents/i18n-s1XrKcD2.js.map +0 -1
  142. package/dist/mosterdcomponents/index-DkY-NQj0.js.map +0 -1
  143. package/dist/mosterdcomponents/index-DwF_Sp__.js.map +0 -1
  144. package/dist/mosterdcomponents/index.esm.js.map +0 -1
  145. package/dist/mosterdcomponents/mosterdcomponents.esm.js.map +0 -1
  146. package/dist/mosterdcomponents/p-69452249.entry.js +0 -1
  147. package/dist/mosterdcomponents/p-_tsCCkAi.js +0 -2
  148. package/dist/mosterdcomponents/quill-C9pgw_k-.js.map +0 -1
  149. package/dist/mosterdcomponents/validation-Br9k2Ztw.js.map +0 -1
@@ -1,19 +1,12 @@
1
- import { h, Host } from "@stencil/core";
2
- import { CellRenderer } from "../../utils/cell-renderer";
3
- import { t } from "../../utils/i18n";
4
- import { formatNumber, formatPercentage, formatCurrency } from "../../utils/format";
5
- const BUFFER = 10;
6
- /** Wacht deze tijd (ms) na het laatste scroll-event voordat pagina's worden
7
- * aangevraagd. Pagina's die de gebruiker snel voorbij scrollt worden zo geskipt. */
8
- const REQUEST_DEBOUNCE_MS = 150;
1
+ import { h, Host, writeTask } from "@stencil/core";
2
+ import { t } from "../../../utils/i18n";
3
+ import { buildListPath } from "../../../utils/query-params";
4
+ import { TEXT_TYPES, NON_INTERACTIVE_TYPES, parseDefaultSort, buildSortParam, buildTableQueryParams, buildAggregationQs, filterHasValue, normalizeDatetimeFilter, datetimeFilterToDisplay, } from "./table-query";
5
+ import { FilterIcon, TableCell, TotalsRow, TextblockModal, JsonModal, Toolbar } from "./table-parts";
6
+ import { FilterPopup } from "./table-filter-popup";
7
+ import { REQUEST_DEBOUNCE_MS, visibleCount, computeWindow, pageRange, getRowFromPages, computeEffectiveTotal, isTotalKnownFromPages, } from "./virtual-scroll";
9
8
  /** Breedte van de filterpopup in px — voor overflow-correctie. */
10
9
  const POPUP_WIDTH = 280;
11
- const TEXT_TYPES = new Set(['TEXT', 'TEXTBLOCK', 'EMAIL', 'HYPERLINK']);
12
- const NUMERIC_TYPES = new Set(['INTEGER', 'DECIMAL', 'PERCENTAGE', 'CURRENCY']);
13
- const DATE_TYPES = new Set(['DATE', 'DATETIME', 'TIME']);
14
- const NO_FILTER_TYPES = new Set(['FILE', 'IMAGE']);
15
- /** Column types that cannot be sorted or filtered (not stored in PostgreSQL). */
16
- const NON_INTERACTIVE_TYPES = new Set(['LONGTEXT', 'JSON', 'FILE', 'IMAGE']);
17
10
  export class MrdTable {
18
11
  constructor() {
19
12
  // ── Non-state internals ────────────────────────────────────────────────────
@@ -23,6 +16,8 @@ export class MrdTable {
23
16
  this.keydownHandler = null;
24
17
  this.createPickerClickHandler = null;
25
18
  this.viewPopoverClickHandler = null;
19
+ /** Guards against scheduling more than one column-width measurement per freeze. */
20
+ this.colWidthMeasureScheduled = false;
26
21
  // ── Props ──────────────────────────────────────────────────────────────────
27
22
  /** The VIEW or RELATED_VIEW layout item. Contains view config, dataClass, fromClass, actions etc. */
28
23
  this.item = null;
@@ -79,13 +74,10 @@ export class MrdTable {
79
74
  this.minKnownTotal = 0;
80
75
  this.handleScroll = (e) => {
81
76
  const scroller = e.currentTarget;
82
- const scrollTop = scroller.scrollTop;
83
- const total = this.baseTotal;
84
- const visStart = Math.floor(scrollTop / this.rowHeight);
85
- const visEnd = Math.min(visStart + this.visibleCount(), total - 1);
86
- this.scrollTop = scrollTop;
87
- this.renderStart = Math.max(0, visStart - BUFFER);
88
- this.renderEnd = Math.min(total - 1, visEnd + BUFFER);
77
+ const { renderStart, renderEnd } = computeWindow(scroller.scrollTop, this.rowHeight, this.tableHeight, this.baseTotal);
78
+ this.scrollTop = scroller.scrollTop;
79
+ this.renderStart = renderStart;
80
+ this.renderEnd = renderEnd;
89
81
  this.requestPagesForWindow(this.renderStart, this.renderEnd);
90
82
  };
91
83
  }
@@ -107,16 +99,9 @@ export class MrdTable {
107
99
  }
108
100
  // ── Helpers ────────────────────────────────────────────────────────────────
109
101
  applyDefaultSort(defaultSort) {
110
- var _a;
111
- if (defaultSort) {
112
- const parts = defaultSort.split(',');
113
- this.sortField = parts[0].trim();
114
- this.sortDir = ((_a = parts[1]) === null || _a === void 0 ? void 0 : _a.trim()) === 'desc' ? 'desc' : 'asc';
115
- }
116
- else {
117
- this.sortField = '';
118
- this.sortDir = 'asc';
119
- }
102
+ const { field, dir } = parseDefaultSort(defaultSort);
103
+ this.sortField = field;
104
+ this.sortDir = dir;
120
105
  }
121
106
  // ── Public API ─────────────────────────────────────────────────────────────
122
107
  /**
@@ -133,6 +118,7 @@ export class MrdTable {
133
118
  this.loadedPages = new Map();
134
119
  this.requestedPages = new Set();
135
120
  this.colWidths = [];
121
+ this.colWidthMeasureScheduled = false;
136
122
  this.scrollTop = 0;
137
123
  this.renderStart = 0;
138
124
  // Always fill the visible viewport on init — totalElements may be stale from a
@@ -213,21 +199,34 @@ export class MrdTable {
213
199
  }
214
200
  }
215
201
  componentDidRender() {
216
- if (this.colWidths.length === 0 && this.loadedPages.size > 0 && this.totalElements > 0) {
217
- const ths = this.el.querySelectorAll('.mrd-table__header');
218
- if (ths.length > 0) {
219
- this.colWidths = Array.from(ths).map(th => th.offsetWidth);
220
- }
202
+ // Freeze header widths once the first data page has rendered. The measurement
203
+ // reads offsetWidth and writes the colWidths @State, which would trigger a
204
+ // re-render *during* the render cycle if done synchronously here. Defer it to a
205
+ // writeTask so the state mutation happens outside the render pass (avoids the
206
+ // Stencil "state/prop changed during rendering" warning and potential loops).
207
+ if (this.colWidths.length === 0 &&
208
+ !this.colWidthMeasureScheduled &&
209
+ this.loadedPages.size > 0 &&
210
+ this.totalElements > 0) {
211
+ this.colWidthMeasureScheduled = true;
212
+ writeTask(() => {
213
+ this.colWidthMeasureScheduled = false;
214
+ // Re-check: state may have changed (e.g. a reset) between scheduling and running.
215
+ if (this.colWidths.length !== 0)
216
+ return;
217
+ const ths = this.el.querySelectorAll('.mrd-table__header');
218
+ if (ths.length > 0) {
219
+ this.colWidths = Array.from(ths).map(th => th.offsetWidth);
220
+ }
221
+ });
221
222
  }
222
223
  }
223
224
  // ── Paging / scroll helpers ────────────────────────────────────────────────
224
225
  visibleCount() {
225
- return Math.ceil(this.tableHeight / this.rowHeight);
226
+ return visibleCount(this.tableHeight, this.rowHeight);
226
227
  }
227
228
  sortParam() {
228
- if (!this.sortField)
229
- return '';
230
- return this.sortDir === 'desc' ? `${this.sortField},desc` : this.sortField;
229
+ return buildSortParam(this.sortField, this.sortDir);
231
230
  }
232
231
  /** Stable ordered list: primary view first, then alternatives (from the item prop). */
233
232
  get allViews() {
@@ -253,14 +252,16 @@ export class MrdTable {
253
252
  * VIEW: /excel/{dataClass}
254
253
  * RELATED_VIEW: /excel/{fromClass}/{parentId}/{dataClass} */
255
254
  buildExcelPath() {
256
- var _a, _b, _c, _d;
255
+ var _a;
257
256
  const v = this.allViews[this.activeViewIdx];
258
257
  if (!v)
259
258
  return '';
260
- if (((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === 'RELATED_VIEW') {
261
- return `/excel/${(_b = v.fromClass) !== null && _b !== void 0 ? _b : ''}/${this.parentId}/${(_c = v.dataClass) !== null && _c !== void 0 ? _c : ''}`;
262
- }
263
- return `/excel/${(_d = v.dataClass) !== null && _d !== void 0 ? _d : ''}`;
259
+ return '/excel' + buildListPath({
260
+ isRelatedView: ((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === 'RELATED_VIEW',
261
+ fromClass: v.fromClass,
262
+ parentId: this.parentId,
263
+ dataClass: v.dataClass,
264
+ });
264
265
  }
265
266
  buildActionDetail(action, basicType) {
266
267
  var _a, _b, _c;
@@ -280,80 +281,28 @@ export class MrdTable {
280
281
  * VIEW: /{dataClass}
281
282
  * RELATED_VIEW: /{fromClass}/{parentId}/{dataClass} */
282
283
  buildDataPath() {
283
- var _a, _b, _c, _d;
284
+ var _a;
284
285
  const v = this.allViews[this.activeViewIdx];
285
286
  if (!v)
286
287
  return '';
287
- if (((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === 'RELATED_VIEW') {
288
- return `/${(_b = v.fromClass) !== null && _b !== void 0 ? _b : ''}/${this.parentId}/${(_c = v.dataClass) !== null && _c !== void 0 ? _c : ''}`;
289
- }
290
- return `/${(_d = v.dataClass) !== null && _d !== void 0 ? _d : ''}`;
288
+ return buildListPath({
289
+ isRelatedView: ((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === 'RELATED_VIEW',
290
+ fromClass: v.fromClass,
291
+ parentId: this.parentId,
292
+ dataClass: v.dataClass,
293
+ });
291
294
  }
292
295
  /** Build query params for a page request from current sort, view filters, filterClass and active column filters. */
293
296
  buildQueryParams(page) {
294
- var _a, _b, _c, _d, _e, _f, _g;
297
+ var _a;
295
298
  const v = this.allViews[this.activeViewIdx];
296
- const p = new URLSearchParams();
297
- if (page > 0)
298
- p.set('page', String(page));
299
- const sort = this.sortParam();
300
- if (sort)
301
- p.set('sort', sort);
302
- const filterClass = v === null || v === void 0 ? void 0 : v.filterClass;
303
- if (filterClass)
304
- p.set('type', filterClass);
305
- 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 : [])) {
306
- if (!f.name)
307
- continue;
308
- if (f.operator === 'EMPTY') {
309
- p.set(f.name, '');
310
- continue;
311
- }
312
- if (f.operator === 'NOT_EMPTY') {
313
- p.set(f.name + '_notempty', 'true');
314
- continue;
315
- }
316
- if (f.operator === 'STARTS_WITH') {
317
- p.set(f.name + '_startswith', String((_c = f.value) !== null && _c !== void 0 ? _c : ''));
318
- continue;
319
- }
320
- if (f.operator === 'FROM') {
321
- p.set(f.name + '_from', String((_d = f.value) !== null && _d !== void 0 ? _d : ''));
322
- continue;
323
- }
324
- if (f.operator === 'TO') {
325
- p.set(f.name + '_to', String((_e = f.value) !== null && _e !== void 0 ? _e : ''));
326
- continue;
327
- }
328
- if (f.value != null) {
329
- p.set(f.name, String(f.value));
330
- }
331
- }
332
- for (const f of this.activeFilters.values()) {
333
- if (f.operator === 'isEmpty') {
334
- p.set(f.field, '');
335
- continue;
336
- }
337
- if (f.operator === 'isNotEmpty') {
338
- p.set(f.field + '_notempty', 'true');
339
- continue;
340
- }
341
- if (f.operator === 'startsWith') {
342
- p.set(f.field + '_startswith', String((_f = f.value) !== null && _f !== void 0 ? _f : ''));
343
- continue;
344
- }
345
- if ((_g = f.values) === null || _g === void 0 ? void 0 : _g.length) {
346
- p.set(f.field, f.values.join(','));
347
- continue;
348
- }
349
- if (f.value != null)
350
- p.set(f.field, String(f.value));
351
- if (f.from != null)
352
- p.set(f.field + '_from', String(f.from));
353
- if (f.to != null)
354
- p.set(f.field + '_to', String(f.to));
355
- }
356
- return p.toString();
299
+ return buildTableQueryParams({
300
+ page,
301
+ sort: this.sortParam(),
302
+ filterClass: v === null || v === void 0 ? void 0 : v.filterClass,
303
+ viewFilters: (_a = v === null || v === void 0 ? void 0 : v.view) === null || _a === void 0 ? void 0 : _a.filter,
304
+ activeFilters: this.activeFilters.values(),
305
+ });
357
306
  }
358
307
  get columns() {
359
308
  var _a, _b, _c;
@@ -408,11 +357,7 @@ export class MrdTable {
408
357
  isTotalKnown() {
409
358
  if (this.aggregationsTotal != null)
410
359
  return true;
411
- for (const rows of this.loadedPages.values()) {
412
- if (rows.length < this.pageSize)
413
- return true;
414
- }
415
- return false;
360
+ return isTotalKnownFromPages(this.loadedPages, this.pageSize);
416
361
  }
417
362
  /** Effective total: aggregations-response > totalElements prop > minKnownTotal from setPage(). */
418
363
  get baseTotal() {
@@ -423,61 +368,9 @@ export class MrdTable {
423
368
  return this.minKnownTotal;
424
369
  }
425
370
  // ── Aggregation helpers ────────────────────────────────────────────────────
426
- buildAggregationParams() {
427
- var _a;
428
- const groups = { sum: [], avg: [], count: [] };
429
- for (const col of this.columns) {
430
- if (col.type !== 'FIELD' || !col.aggregate)
431
- continue;
432
- const fn = col.aggregate.toLowerCase();
433
- if (fn in groups)
434
- groups[fn].push((_a = col.name) !== null && _a !== void 0 ? _a : '');
435
- }
436
- const params = {};
437
- if (groups.sum.length)
438
- params.sum = groups.sum;
439
- if (groups.avg.length)
440
- params.avg = groups.avg;
441
- if (groups.count.length)
442
- params.count = groups.count;
443
- return Object.keys(params).length > 0 ? params : null;
444
- }
445
- buildAggregationQs() {
446
- var _a, _b, _c;
447
- const p = new URLSearchParams(this.buildQueryParams(0));
448
- p.delete('page');
449
- p.delete('sort');
450
- const groups = this.buildAggregationParams();
451
- if ((_a = groups === null || groups === void 0 ? void 0 : groups.sum) === null || _a === void 0 ? void 0 : _a.length)
452
- p.set('sum', groups.sum.join(','));
453
- if ((_b = groups === null || groups === void 0 ? void 0 : groups.avg) === null || _b === void 0 ? void 0 : _b.length)
454
- p.set('avg', groups.avg.join(','));
455
- if ((_c = groups === null || groups === void 0 ? void 0 : groups.count) === null || _c === void 0 ? void 0 : _c.length)
456
- p.set('count', groups.count.join(','));
457
- return p.toString();
458
- }
459
371
  emitLoadAggregations() {
460
- this.mrdLoadAggregations.emit({ path: this.buildDataPath(), qs: this.buildQueryParams(0), aggQs: this.buildAggregationQs() });
461
- }
462
- renderAggregationValue(col) {
463
- var _a;
464
- if (col.type !== 'FIELD' || !col.aggregate || !this.aggregations)
465
- return '';
466
- const fn = col.aggregate.toLowerCase();
467
- const aggData = this.aggregations[fn];
468
- const val = typeof aggData === 'object' && aggData !== null
469
- ? aggData[(_a = col.name) !== null && _a !== void 0 ? _a : '']
470
- : undefined;
471
- if (val == null)
472
- return '';
473
- const dt = col.dataType;
474
- if (dt === 'INTEGER')
475
- return formatNumber(val, this.locale, { maximumFractionDigits: 0 });
476
- if (dt === 'PERCENTAGE')
477
- return formatPercentage(val, this.locale);
478
- if (dt === 'CURRENCY' && col.currencyCode)
479
- return formatCurrency(val, col.currencyCode, this.locale);
480
- return formatNumber(val, this.locale);
372
+ const qs = this.buildQueryParams(0);
373
+ this.mrdLoadAggregations.emit({ path: this.buildDataPath(), qs, aggQs: buildAggregationQs(qs, this.columns) });
481
374
  }
482
375
  // ── Reset pagination ───────────────────────────────────────────────────────
483
376
  /** Reset pagination state and scroll to top (used after sort or filter change). */
@@ -490,6 +383,7 @@ export class MrdTable {
490
383
  this.loadedPages = new Map();
491
384
  this.requestedPages = new Set();
492
385
  this.colWidths = [];
386
+ this.colWidthMeasureScheduled = false;
493
387
  this.scrollTop = 0;
494
388
  this.renderStart = 0;
495
389
  this.minKnownTotal = 0;
@@ -519,8 +413,7 @@ export class MrdTable {
519
413
  this.emitPagesForWindow(this.renderStart, this.renderEnd);
520
414
  }
521
415
  emitPagesForWindow(start, end) {
522
- const firstPage = Math.floor(start / this.pageSize);
523
- const lastPage = Math.floor(end / this.pageSize);
416
+ const { firstPage, lastPage } = pageRange(start, end, this.pageSize);
524
417
  const next = new Set(this.requestedPages);
525
418
  let changed = false;
526
419
  for (let p = firstPage; p <= lastPage; p++) {
@@ -534,13 +427,10 @@ export class MrdTable {
534
427
  this.requestedPages = next;
535
428
  }
536
429
  getRow(i) {
537
- var _a;
538
- const page = this.loadedPages.get(Math.floor(i / this.pageSize));
539
- return (_a = page === null || page === void 0 ? void 0 : page[i % this.pageSize]) !== null && _a !== void 0 ? _a : null;
430
+ return getRowFromPages(this.loadedPages, i, this.pageSize);
540
431
  }
541
432
  requestPagesForWindow(start, end) {
542
- const firstPage = Math.floor(start / this.pageSize);
543
- const lastPage = Math.floor(end / this.pageSize);
433
+ const { firstPage, lastPage } = pageRange(start, end, this.pageSize);
544
434
  let anyNew = false;
545
435
  for (let p = firstPage; p <= lastPage; p++) {
546
436
  if (!this.loadedPages.has(p) && !this.requestedPages.has(p) && !this.pendingPages.has(p)) {
@@ -602,17 +492,7 @@ export class MrdTable {
602
492
  // If from and to cover the same local day it was an exact-date filter — restore
603
493
  // to exact mode so the user sees the single-date input again.
604
494
  if (dataType === 'DATETIME' && existing && existing.operator !== 'isEmpty' && existing.operator !== 'isNotEmpty') {
605
- const display = Object.assign({}, existing);
606
- if (typeof display.from === 'string' && display.from)
607
- display.from = this.utcISOToLocalDate(display.from);
608
- if (typeof display.to === 'string' && display.to)
609
- display.to = this.utcISOToLocalDateExclusiveEnd(display.to);
610
- if (display.from && display.to && display.from === display.to) {
611
- this.pendingFilter = Object.assign(Object.assign({}, display), { value: display.from, from: undefined, to: undefined });
612
- }
613
- else {
614
- this.pendingFilter = display;
615
- }
495
+ this.pendingFilter = datetimeFilterToDisplay(existing);
616
496
  }
617
497
  else {
618
498
  this.pendingFilter = existing ? Object.assign({}, existing) : { field: name, dataType, operator: defaultOperator };
@@ -678,81 +558,15 @@ export class MrdTable {
678
558
  const current = (_b = (_a = this.pendingFilter) === null || _a === void 0 ? void 0 : _a.values) !== null && _b !== void 0 ? _b : [];
679
559
  this.pendingFilter = Object.assign(Object.assign({}, this.pendingFilter), { values: checked ? [...current, key] : current.filter(k => k !== key) });
680
560
  }
681
- filterHasValue(f) {
682
- if (f.operator === 'isEmpty' || f.operator === 'isNotEmpty')
683
- return true;
684
- if (f.values !== undefined && f.values.length > 0)
685
- return true;
686
- if (f.value != null && f.value !== '')
687
- return true;
688
- if (typeof f.value === 'boolean')
689
- return true;
690
- if (f.from != null && f.from !== '')
691
- return true;
692
- if (f.to != null && f.to !== '')
693
- return true;
694
- return false;
695
- }
696
- // Convert a local "YYYY-MM-DD" date string to the UTC ISO string at the
697
- // start of that local day (midnight). new Date(y, m, d) uses local time.
698
- dateLocalToUTCStart(dateStr) {
699
- if (!dateStr)
700
- return dateStr;
701
- const [year, month, day] = dateStr.split('-').map(Number);
702
- return new Date(year, month - 1, day).toISOString().replace(/\.\d{3}Z$/, 'Z');
703
- }
704
- // Start of the day AFTER the given local date (exclusive range end).
705
- dateLocalToUTCEndExclusive(dateStr) {
706
- if (!dateStr)
707
- return dateStr;
708
- const [year, month, day] = dateStr.split('-').map(Number);
709
- return new Date(year, month - 1, day + 1).toISOString().replace(/\.\d{3}Z$/, 'Z');
710
- }
711
- // Convert a stored UTC ISO string back to the local "YYYY-MM-DD" date.
712
- utcISOToLocalDate(utcStr) {
713
- if (!utcStr)
714
- return utcStr;
715
- const d = new Date(utcStr);
716
- if (isNaN(d.getTime()))
717
- return utcStr;
718
- return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
719
- }
720
- // The stored "to" value is the exclusive end (midnight of the next day).
721
- // Subtract one day to recover the local date the user entered.
722
- utcISOToLocalDateExclusiveEnd(utcStr) {
723
- if (!utcStr)
724
- return utcStr;
725
- const d = new Date(utcStr);
726
- if (isNaN(d.getTime()))
727
- return utcStr;
728
- d.setDate(d.getDate() - 1);
729
- return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
730
- }
731
561
  applyFilter() {
732
562
  const f = this.pendingFilter;
733
563
  if (!(f === null || f === void 0 ? void 0 : f.field)) {
734
564
  this.closeFilterPopup();
735
565
  return;
736
566
  }
737
- // For DATETIME fields the user enters local dates; convert to UTC ISO strings.
738
- // Exact date → range covering the full local day (from = midnight, to = next midnight).
739
- // "to" is always the exclusive end (midnight of the next local day).
740
- let normalized = Object.assign({}, f);
741
- if (f.dataType === 'DATETIME' && f.operator !== 'isEmpty' && f.operator !== 'isNotEmpty') {
742
- if (typeof normalized.value === 'string' && normalized.value) {
743
- normalized.from = this.dateLocalToUTCStart(normalized.value);
744
- normalized.to = this.dateLocalToUTCEndExclusive(normalized.value);
745
- normalized.value = undefined;
746
- }
747
- else {
748
- if (typeof normalized.from === 'string' && normalized.from)
749
- normalized.from = this.dateLocalToUTCStart(normalized.from);
750
- if (typeof normalized.to === 'string' && normalized.to)
751
- normalized.to = this.dateLocalToUTCEndExclusive(normalized.to);
752
- }
753
- }
567
+ const normalized = normalizeDatetimeFilter(f);
754
568
  const next = new Map(this.activeFilters);
755
- if (this.filterHasValue(normalized)) {
569
+ if (filterHasValue(normalized)) {
756
570
  next.set(normalized.field, normalized);
757
571
  }
758
572
  else {
@@ -807,140 +621,53 @@ export class MrdTable {
807
621
  toggleViewPopover(e) {
808
622
  e.stopPropagation();
809
623
  if (this.viewPopoverOpen) {
810
- this.viewPopoverOpen = false;
811
- if (this.viewPopoverClickHandler) {
812
- document.removeEventListener('click', this.viewPopoverClickHandler);
813
- this.viewPopoverClickHandler = null;
814
- }
624
+ this.closeViewPopover();
815
625
  return;
816
626
  }
817
627
  this.viewPopoverOpen = true;
818
- this.viewPopoverClickHandler = () => {
819
- this.viewPopoverOpen = false;
628
+ this.viewPopoverClickHandler = () => this.closeViewPopover();
629
+ document.addEventListener('click', this.viewPopoverClickHandler);
630
+ }
631
+ closeViewPopover() {
632
+ this.viewPopoverOpen = false;
633
+ if (this.viewPopoverClickHandler) {
820
634
  document.removeEventListener('click', this.viewPopoverClickHandler);
821
635
  this.viewPopoverClickHandler = null;
822
- };
823
- document.addEventListener('click', this.viewPopoverClickHandler);
636
+ }
824
637
  }
825
638
  // ── Render: toolbar ────────────────────────────────────────────────────────
826
639
  renderToolbar() {
827
640
  var _a;
828
- const filterCount = this.activeFilters.size;
829
- const actions = this.tableActions;
830
- const allViews = this.allViews;
831
- const hasActions = actions.length > 0;
832
- const hasViewSwitcher = allViews.length > 1;
833
- 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("div", { class: "mrd-table__view-switcher" }, h("button", { class: "mrd-table__view-arrow", "aria-label": "Previous view", onClick: () => this.handleViewSwitch((this.activeViewIdx - 1 + allViews.length) % allViews.length) }, "\u25C0"), h("div", { class: "mrd-table__view-title-wrap" }, h("button", { class: "mrd-table__view-title", onClick: (e) => this.toggleViewPopover(e) }, (_a = allViews[this.activeViewIdx]) === null || _a === void 0 ? void 0 : _a.label), this.viewPopoverOpen && (h("div", { class: "mrd-table__view-popover", onClick: (e) => e.stopPropagation() }, allViews.map((v, i) => (h("button", { key: String(i), class: `mrd-table__view-popover-item${i === this.activeViewIdx ? ' mrd-table__view-popover-item--active' : ''}`, onClick: () => {
834
- if (i !== this.activeViewIdx)
835
- this.handleViewSwitch(i);
836
- this.viewPopoverOpen = false;
837
- if (this.viewPopoverClickHandler) {
838
- document.removeEventListener('click', this.viewPopoverClickHandler);
839
- this.viewPopoverClickHandler = null;
840
- }
841
- } }, v.label)))))), h("button", { class: "mrd-table__view-arrow", "aria-label": "Next view", onClick: () => this.handleViewSwitch((this.activeViewIdx + 1) % allViews.length) }, "\u25B6")))), hasActions && (h("div", { class: "mrd-table__toolbar-right" }, actions.map(a => {
842
- var _a, _b, _c;
843
- const createTypes = a.action === 'create' ? (_a = this.item) === null || _a === void 0 ? void 0 : _a.createTypes : null;
844
- if (createTypes === null || createTypes === void 0 ? void 0 : createTypes.length) {
845
- return (h("div", { class: "mrd-table__create-picker-wrap", key: `action-${a.action}` }, h("button", { class: `mrd-table__action mrd-table__action--${(_b = a.variant) !== null && _b !== void 0 ? _b : 'secondary'}`, onClick: () => this.toggleCreatePicker() }, a.icon
846
- ? h("svg", { class: "mrd-table__action-icon", "aria-hidden": "true" }, h("use", { href: a.icon }))
847
- : a.label, h("span", { class: "mrd-table__action-tooltip" }, a.label)), this.createPickerOpen && (h("div", { class: "mrd-table__create-picker" }, createTypes.map(ct => (h("button", { key: ct.type, class: "mrd-table__create-picker-item", onClick: () => {
848
- this.mrdAction.emit(this.buildActionDetail('create', ct.type));
849
- this.closeCreatePicker();
850
- } }, ct.label)))))));
851
- }
852
- return (h("button", { key: `action-${a.action}`, class: `mrd-table__action mrd-table__action--${(_c = a.variant) !== null && _c !== void 0 ? _c : 'secondary'}`, disabled: a.disabled, onClick: () => this.mrdAction.emit(this.buildActionDetail(a.action)) }, a.icon
853
- ? h("svg", { class: "mrd-table__action-icon", "aria-hidden": "true" }, h("use", { href: a.icon }))
854
- : a.label, h("span", { class: "mrd-table__action-tooltip" }, a.label)));
855
- })))));
641
+ return (h(Toolbar, { locale: this.locale, filterMode: this.filterMode, filterCount: this.activeFilters.size, actions: this.tableActions, views: this.allViews, activeViewIdx: this.activeViewIdx, viewPopoverOpen: this.viewPopoverOpen, createPickerOpen: this.createPickerOpen, createTypes: (_a = this.item) === null || _a === void 0 ? void 0 : _a.createTypes, cb: {
642
+ onFilterToggle: () => this.handleFilterToggle(),
643
+ onClearAllFilters: () => this.clearAllFilters(),
644
+ onViewSwitch: idx => this.handleViewSwitch(idx),
645
+ onToggleViewPopover: e => this.toggleViewPopover(e),
646
+ onCloseViewPopover: () => this.closeViewPopover(),
647
+ onToggleCreatePicker: () => this.toggleCreatePicker(),
648
+ onCreate: basicType => {
649
+ this.mrdAction.emit(this.buildActionDetail('create', basicType));
650
+ this.closeCreatePicker();
651
+ },
652
+ onAction: action => this.mrdAction.emit(this.buildActionDetail(action)),
653
+ } }));
856
654
  }
857
655
  // ── Render: filter popup ───────────────────────────────────────────────────
858
- renderFilterEditor(col) {
859
- var _a, _b, _c, _d, _e, _f, _g;
860
- const pf = (_a = this.pendingFilter) !== null && _a !== void 0 ? _a : {};
861
- const dataType = this.colDataType(col);
862
- if (NO_FILTER_TYPES.has(dataType)) {
863
- return h("p", { class: "mrd-table__filter-no-support" }, t('filter_no_support', this.locale));
864
- }
865
- if (dataType === 'BOOLEAN') {
866
- const boolOp = pf.operator;
867
- const noValueOp = boolOp === 'isEmpty' || boolOp === 'isNotEmpty';
868
- return (h("div", { class: "mrd-table__filter-radio-group" }, [
869
- { labelKey: 'filter_all', value: null },
870
- { labelKey: 'yes', value: true },
871
- { labelKey: 'no', value: false },
872
- ].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))));
873
- }
874
- if (dataType === 'LIST') {
875
- const items = (_b = col.listItems) !== null && _b !== void 0 ? _b : [];
876
- const selected = (_c = pf.values) !== null && _c !== void 0 ? _c : [];
877
- 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)))));
878
- }
879
- if (TEXT_TYPES.has(dataType) || dataType === 'RELATION') {
880
- const op = (_d = pf.operator) !== null && _d !== void 0 ? _d : 'startsWith';
881
- const noInput = op === 'isEmpty' || op === 'isNotEmpty';
882
- return (h("div", { class: "mrd-table__filter-editor" }, h("select", { class: "mrd-table__filter-select", onChange: (e) => this.setPending('operator', e.target.value) }, [
883
- { val: 'startsWith', labelKey: 'filter_starts_with' },
884
- { val: 'equals', labelKey: 'filter_equals' },
885
- { val: 'isEmpty', labelKey: 'filter_is_empty' },
886
- { val: 'isNotEmpty', labelKey: 'filter_is_not_empty' },
887
- ].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) }))));
888
- }
889
- if (NUMERIC_TYPES.has(dataType)) {
890
- const numOp = pf.operator;
891
- const noInput = numOp === 'isEmpty' || numOp === 'isNotEmpty';
892
- const rangeMode = !noInput && (pf.from !== undefined || pf.to !== undefined);
893
- return (h("div", { class: "mrd-table__filter-editor" }, h("select", { class: "mrd-table__filter-select", onChange: (e) => {
894
- const val = e.target.value;
895
- if (val === 'isEmpty' || val === 'isNotEmpty') {
896
- this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: val, value: undefined, from: undefined, to: undefined });
897
- }
898
- else {
899
- this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: undefined });
900
- }
901
- } }, h("option", { value: "", selected: !noInput }, t('filter_has_value', this.locale)), h("option", { value: "isEmpty", selected: numOp === 'isEmpty' }, t('filter_is_empty', this.locale)), h("option", { value: "isNotEmpty", selected: numOp === '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: `nm-${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: `nm-${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: "number", class: "mrd-table__filter-input", value: pf.value != null ? String(pf.value) : '', onInput: (e) => this.setPending('value', e.target.value) })) : (h("div", { class: "mrd-table__filter-range" }, h("input", { type: "number", 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("span", { class: "mrd-table__filter-range-sep" }, "\u2013"), h("input", { type: "number", 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) })))))));
902
- }
903
- if (dataType === 'DATETIME') {
904
- const dtOp = pf.operator;
905
- const noInput = dtOp === 'isEmpty' || dtOp === 'isNotEmpty';
906
- const rangeMode = !noInput && (pf.from !== undefined || pf.to !== undefined);
907
- return (h("div", { class: "mrd-table__filter-editor" }, h("select", { class: "mrd-table__filter-select", onChange: (e) => {
908
- const val = e.target.value;
909
- if (val === 'isEmpty' || val === 'isNotEmpty') {
910
- this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: val, value: undefined, from: undefined, to: undefined });
911
- }
912
- else {
913
- this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: undefined });
914
- }
915
- } }, 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) })))))));
916
- }
917
- if (DATE_TYPES.has(dataType)) {
918
- const inputType = dataType === 'DATE' ? 'date' : 'time';
919
- const dtdOp = pf.operator;
920
- const noInput = dtdOp === 'isEmpty' || dtdOp === 'isNotEmpty';
921
- const rangeMode = !noInput && (pf.from !== undefined || pf.to !== undefined);
922
- return (h("div", { class: "mrd-table__filter-editor" }, h("select", { class: "mrd-table__filter-select", onChange: (e) => {
923
- const val = e.target.value;
924
- if (val === 'isEmpty' || val === 'isNotEmpty') {
925
- this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: val, value: undefined, from: undefined, to: undefined });
926
- }
927
- else {
928
- this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: undefined });
929
- }
930
- } }, 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) })))))));
931
- }
932
- return null;
933
- }
934
656
  renderFilterPopup() {
935
- var _a;
936
657
  if (!this.openFilterCol || !this.pendingFilter)
937
658
  return null;
938
659
  const col = this.columns.find(c => this.colName(c) === this.openFilterCol);
939
660
  if (!col)
940
661
  return null;
941
- const label = (_a = col.label) !== null && _a !== void 0 ? _a : this.openFilterCol;
942
- const sortActive = this.sortField === this.openFilterCol;
943
- 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)))));
662
+ return (h(FilterPopup, { col: col, dataType: this.colDataType(col), openFilterCol: this.openFilterCol, pendingFilter: this.pendingFilter, popupPos: this.popupPos, sortField: this.sortField, sortDir: this.sortDir, locale: this.locale, cb: {
663
+ onSetPending: (key, val) => this.setPending(key, val),
664
+ onReplacePending: pf => (this.pendingFilter = pf),
665
+ onToggleValue: (key, checked) => this.togglePendingValue(key, checked),
666
+ onApplySort: dir => this.applySort(col, dir),
667
+ onApply: () => this.applyFilter(),
668
+ onClear: () => this.clearFilter(),
669
+ onClose: () => this.closeFilterPopup(),
670
+ } }));
944
671
  }
945
672
  // ── Render: footer ────────────────────────────────────────────────────────
946
673
  renderFooter(rowCount, effectiveTotal, isTotalKnown = true) {
@@ -965,54 +692,11 @@ export class MrdTable {
965
692
  }
966
693
  // ── Render: cell ──────────────────────────────────────────────────────────
967
694
  renderCell(col, row) {
968
- var _a, _b, _c;
969
- const numericTypes = new Set(['INTEGER', 'DECIMAL', 'PERCENTAGE', 'CURRENCY']);
970
- const dataType = (_a = col.dataType) !== null && _a !== void 0 ? _a : '';
971
- const isNumeric = col.type === 'FIELD' && numericTypes.has(dataType);
972
- const isFile = col.type === 'FIELD' && (dataType === 'FILE' || dataType === 'IMAGE');
973
- if (isFile) {
974
- const name = (_b = col.name) !== null && _b !== void 0 ? _b : '';
975
- const fileVal = row === null || row === void 0 ? void 0 : row[name];
976
- const href = fileVal === null || fileVal === void 0 ? void 0 : fileVal.href;
977
- const fileName = fileVal === null || fileVal === void 0 ? void 0 : fileVal.fileName;
978
- return (h("td", { class: "mrd-table__cell" }, href && fileName ? (h("button", { class: "mrd-table__file-btn", title: fileName, onClick: (e) => {
979
- e.stopPropagation();
980
- this.mrdDownload.emit({ href, fileName });
981
- } }, 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))) : ''));
982
- }
983
- if (dataType === 'JSON') {
984
- const name = (_c = col.name) !== null && _c !== void 0 ? _c : '';
985
- const rawValue = name ? row === null || row === void 0 ? void 0 : row[name] : undefined;
986
- if (rawValue == null || rawValue === '')
987
- return h("td", { class: "mrd-table__cell" });
988
- const compactHtml = CellRenderer.formatJson(rawValue, true);
989
- const prettyHtml = CellRenderer.formatJson(rawValue, false);
990
- return (h("td", { class: "mrd-table__cell" }, h("span", { class: "mrd-table__json-preview", innerHTML: compactHtml }), h("button", { class: "mrd-table__textblock-btn", onClick: (e) => { e.stopPropagation(); this.openJsonModal(prettyHtml); }, "aria-label": t('textblock_show_more', this.locale) }, "\u22EF")));
991
- }
992
- const TEXTBLOCK_MAX = 200;
993
- if (dataType === 'TEXTBLOCK') {
994
- const full = CellRenderer.render(col, row, this.locale);
995
- if (full.length <= TEXTBLOCK_MAX) {
996
- return h("td", { class: "mrd-table__cell" }, full);
997
- }
998
- const preview = full.slice(0, TEXTBLOCK_MAX) + '…';
999
- return (h("td", { class: "mrd-table__cell" }, preview, h("button", { class: "mrd-table__textblock-btn", onClick: (e) => { e.stopPropagation(); this.openTextblockModal(full); }, "aria-label": t('textblock_show_more', this.locale) }, "\u22EF")));
1000
- }
1001
- const value = CellRenderer.render(col, row, this.locale);
1002
- return (h("td", { class: `mrd-table__cell${isNumeric ? ' mrd-table__cell--numeric' : ''}` }, value));
695
+ return (h(TableCell, { col: col, row: row, locale: this.locale, onDownload: detail => this.mrdDownload.emit(detail), onOpenTextblock: full => this.openTextblockModal(full), onOpenJson: html => this.openJsonModal(html) }));
1003
696
  }
1004
697
  // ── Render: totals row ────────────────────────────────────────────────────
1005
698
  renderTotalsRow() {
1006
- if (!this.aggregations)
1007
- return null;
1008
- if (!this.columns.some(c => c.type === 'FIELD' && c.aggregate))
1009
- return null;
1010
- return (h("tfoot", null, h("tr", { class: "mrd-table__totals-row" }, this.columns.map(col => {
1011
- var _a;
1012
- const val = this.renderAggregationValue(col);
1013
- const isNumeric = col.type === 'FIELD' && NUMERIC_TYPES.has((_a = col.dataType) !== null && _a !== void 0 ? _a : '');
1014
- return (h("td", { class: `mrd-table__totals-cell${isNumeric ? ' mrd-table__totals-cell--numeric' : ''}` }, val));
1015
- }))));
699
+ return h(TotalsRow, { columns: this.columns, aggregations: this.aggregations, locale: this.locale });
1016
700
  }
1017
701
  // ── Render ─────────────────────────────────────────────────────────────────
1018
702
  render() {
@@ -1032,7 +716,7 @@ export class MrdTable {
1032
716
  isFiltered ? 'mrd-table__header--filtered' : '',
1033
717
  this.filterMode ? 'mrd-table__header--sortable' : '',
1034
718
  ].filter(Boolean).join(' ');
1035
- 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()));
719
+ 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 && h(FilterIcon, null)));
1036
720
  }))), 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()));
1037
721
  }
1038
722
  // ── Paginated / virtual-scroll mode ────────────────────────────────────
@@ -1040,12 +724,7 @@ export class MrdTable {
1040
724
  // if any loaded page is shorter than pageSize it is the last page,
1041
725
  // so the true total cannot exceed (pageNum * pageSize + pageRows.length).
1042
726
  // aggregationsTotal (from setAggregations) takes priority over the totalElements prop.
1043
- let effectiveTotal = this.baseTotal;
1044
- for (const [pageNum, pageRows] of this.loadedPages) {
1045
- if (pageRows.length < this.pageSize) {
1046
- effectiveTotal = Math.min(effectiveTotal, pageNum * this.pageSize + pageRows.length);
1047
- }
1048
- }
727
+ const effectiveTotal = computeEffectiveTotal(this.loadedPages, this.pageSize, this.baseTotal);
1049
728
  // Clamp renderEnd to what we actually know exists (-1 when empty)
1050
729
  const clampedEnd = Math.min(this.renderEnd, effectiveTotal - 1);
1051
730
  const colCount = this.columns.length;
@@ -1076,21 +755,14 @@ export class MrdTable {
1076
755
  isActive ? `mrd-table__header--sorted-${this.sortDir}` : '',
1077
756
  isFiltered ? 'mrd-table__header--filtered' : '',
1078
757
  ].filter(Boolean).join(' ');
1079
- 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()));
1080
- }))), 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.isTotalKnown()), this.renderFilterPopup(), this.renderTextblockModal()));
1081
- }
1082
- renderFilterIcon() {
1083
- return (h("span", { class: "mrd-table__filter-icon", "aria-hidden": "true" }, h("svg", { viewBox: "0 0 24 24", width: "14", height: "14", fill: "currentColor" }, h("path", { d: "M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z" }))));
758
+ 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 && h(FilterIcon, null)));
759
+ }))), 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.isTotalKnown()), this.renderFilterPopup(), this.renderTextblockModal(), this.renderJsonModal()));
1084
760
  }
1085
761
  renderTextblockModal() {
1086
- if (this.textblockModal === null)
1087
- return null;
1088
- return (h("div", { class: "mrd-table__modal-backdrop", onClick: () => this.closeTextblockModal(), role: "dialog", "aria-modal": "true" }, h("div", { class: "mrd-table__modal", onClick: (e) => e.stopPropagation() }, h("button", { class: "mrd-table__modal-close", onClick: () => this.closeTextblockModal(), "aria-label": t('close', this.locale) }, "\u2715"), h("p", { class: "mrd-table__modal-text" }, this.textblockModal))));
762
+ return h(TextblockModal, { text: this.textblockModal, locale: this.locale, onClose: () => this.closeTextblockModal() });
1089
763
  }
1090
764
  renderJsonModal() {
1091
- if (this.jsonModal === null)
1092
- return null;
1093
- return (h("div", { class: "mrd-table__modal-backdrop", onClick: () => this.closeJsonModal(), role: "dialog", "aria-modal": "true" }, h("div", { class: "mrd-table__modal", onClick: (e) => e.stopPropagation() }, h("button", { class: "mrd-table__modal-close", onClick: () => this.closeJsonModal(), "aria-label": t('close', this.locale) }, "\u2715"), h("pre", { class: "mrd-table__modal-json", innerHTML: this.jsonModal }))));
765
+ return h(JsonModal, { html: this.jsonModal, locale: this.locale, onClose: () => this.closeJsonModal() });
1094
766
  }
1095
767
  static get is() { return "mrd-table"; }
1096
768
  static get encapsulation() { return "scoped"; }
@@ -1115,7 +787,7 @@ export class MrdTable {
1115
787
  "references": {
1116
788
  "ClientLayoutItem": {
1117
789
  "location": "import",
1118
- "path": "../../types/client-layout",
790
+ "path": "../../../types/client-layout",
1119
791
  "id": "src/types/client-layout.ts::ClientLayoutItem",
1120
792
  "referenceLocation": "ClientLayoutItem"
1121
793
  }
@@ -1455,7 +1127,7 @@ export class MrdTable {
1455
1127
  },
1456
1128
  "AggregationResult": {
1457
1129
  "location": "import",
1458
- "path": "../../types/client-layout",
1130
+ "path": "../../../types/client-layout",
1459
1131
  "id": "src/types/client-layout.ts::AggregationResult",
1460
1132
  "referenceLocation": "AggregationResult"
1461
1133
  }