@mmlogic/components 0.1.9 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +196 -61
- package/dist/cjs/format-DBr-GTvS.js +308 -0
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/mosterdcomponents.cjs.js +1 -1
- package/dist/cjs/mrd-boolean-field_16.cjs.entry.js +108 -117
- package/dist/cjs/mrd-table.cjs.entry.js +318 -62
- package/dist/collection/components/mrd-field/mrd-field.js +26 -2
- package/dist/collection/components/mrd-file-field/mrd-file-field.js +70 -2
- package/dist/collection/components/mrd-file-field/mrd-file-field.scss +13 -0
- package/dist/collection/components/mrd-form/mrd-form.js +28 -1
- package/dist/collection/components/mrd-image-field/mrd-image-field.js +71 -2
- package/dist/collection/components/mrd-image-field/mrd-image-field.scss +26 -2
- package/dist/collection/components/mrd-table/mrd-table.js +386 -62
- package/dist/collection/components/mrd-table/mrd-table.scss +388 -0
- package/dist/collection/dev/app.js +48 -4
- package/dist/collection/dev/sprites.svg +55 -0
- package/dist/collection/utils/i18n.js +144 -0
- package/dist/components/i18n.js +1 -1
- package/dist/components/mrd-field2.js +1 -1
- package/dist/components/mrd-file-field2.js +1 -1
- package/dist/components/mrd-form.js +1 -1
- package/dist/components/mrd-image-field2.js +1 -1
- package/dist/components/mrd-table.js +1 -1
- package/dist/esm/format-EzhfM0uw.js +299 -0
- package/dist/esm/loader.js +1 -1
- package/dist/esm/mosterdcomponents.js +1 -1
- package/dist/esm/mrd-boolean-field_16.entry.js +82 -91
- package/dist/esm/mrd-table.entry.js +318 -62
- package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
- package/dist/mosterdcomponents/p-27f6947a.entry.js +1 -0
- package/dist/mosterdcomponents/p-EzhfM0uw.js +1 -0
- package/dist/mosterdcomponents/p-ca5f9919.entry.js +1 -0
- package/dist/types/components/mrd-field/mrd-field.d.ts +5 -0
- package/dist/types/components/mrd-file-field/mrd-file-field.d.ts +10 -0
- package/dist/types/components/mrd-form/mrd-form.d.ts +5 -0
- package/dist/types/components/mrd-image-field/mrd-image-field.d.ts +10 -0
- package/dist/types/components/mrd-table/mrd-table.d.ts +52 -18
- package/dist/types/components.d.ts +53 -3
- package/dist/types/utils/cell-renderer.d.ts +27 -0
- package/package.json +1 -1
- package/dist/cjs/format-CDw-zie_.js +0 -82
- package/dist/esm/format-Dt-aHxkM.js +0 -74
- package/dist/mosterdcomponents/p-2a8cb2eb.entry.js +0 -1
- package/dist/mosterdcomponents/p-Dt-aHxkM.js +0 -1
- package/dist/mosterdcomponents/p-baf08615.entry.js +0 -1
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
import { h, Host } from "@stencil/core";
|
|
2
2
|
import { CellRenderer } from "../../utils/cell-renderer";
|
|
3
|
+
import { t } from "../../utils/i18n";
|
|
3
4
|
const BUFFER = 10;
|
|
4
5
|
/** Wacht deze tijd (ms) na het laatste scroll-event voordat pagina's worden
|
|
5
6
|
* aangevraagd. Pagina's die de gebruiker snel voorbij scrollt worden zo geskipt. */
|
|
6
7
|
const REQUEST_DEBOUNCE_MS = 150;
|
|
8
|
+
/** Breedte van de filterpopup in px — voor overflow-correctie. */
|
|
9
|
+
const POPUP_WIDTH = 280;
|
|
10
|
+
const TEXT_TYPES = new Set(['TEXT', 'TEXTBLOCK', 'EMAIL', 'HYPERLINK']);
|
|
11
|
+
const NUMERIC_TYPES = new Set(['INTEGER', 'DECIMAL', 'PERCENTAGE', 'CURRENCY']);
|
|
12
|
+
const DATE_TYPES = new Set(['DATE', 'DATETIME', 'TIME']);
|
|
13
|
+
const NO_FILTER_TYPES = new Set(['FILE', 'IMAGE']);
|
|
7
14
|
export class MrdTable {
|
|
8
15
|
constructor() {
|
|
9
|
-
// ──
|
|
10
|
-
/** Pagina's die wachten op debounce-flush. */
|
|
16
|
+
// ── Non-state internals ────────────────────────────────────────────────────
|
|
11
17
|
this.pendingPages = new Set();
|
|
12
|
-
/** Handle van de actieve debounce-timer. */
|
|
13
18
|
this.debounceTimer = null;
|
|
19
|
+
this.outsideClickHandler = null;
|
|
14
20
|
// ── Props ──────────────────────────────────────────────────────────────────
|
|
15
21
|
this.columns = [];
|
|
16
22
|
/** Direct rows (non-paginated mode, used when totalElements === 0). */
|
|
@@ -27,32 +33,45 @@ export class MrdTable {
|
|
|
27
33
|
/** Initial sort applied on load, e.g. "timestamp,desc" or "name".
|
|
28
34
|
* Parsed by init() into sortField + sortDir. */
|
|
29
35
|
this.defaultSort = '';
|
|
36
|
+
/** Toolbar action buttons rendered above the table. */
|
|
37
|
+
this.actions = [];
|
|
30
38
|
// ── Internal state ─────────────────────────────────────────────────────────
|
|
31
|
-
/** Pages injected via setPage(). Always replaced by a new Map to trigger re-render. */
|
|
32
39
|
this.loadedPages = new Map();
|
|
33
|
-
/** Pages already requested via mrdLoadPage (to avoid duplicate events). */
|
|
34
40
|
this.requestedPages = new Set();
|
|
35
|
-
/** Absolute index of the first row currently in the render window. */
|
|
36
41
|
this.renderStart = 0;
|
|
37
|
-
/** Absolute index of the last row currently in the render window. */
|
|
38
42
|
this.renderEnd = 0;
|
|
39
|
-
/** Locked column widths (px) — measured after first page renders, then fixed. */
|
|
40
43
|
this.colWidths = [];
|
|
41
|
-
/** Column currently used for sorting (empty = no sort). */
|
|
42
44
|
this.sortField = '';
|
|
43
|
-
/** Sort direction for sortField. */
|
|
44
45
|
this.sortDir = 'asc';
|
|
46
|
+
/** Whether the filter UI is visible on column headers. */
|
|
47
|
+
this.filterMode = false;
|
|
48
|
+
/** Active filters keyed by field name. */
|
|
49
|
+
this.activeFilters = new Map();
|
|
50
|
+
/** Field name of the currently open filter popup (null = closed). */
|
|
51
|
+
this.openFilterCol = null;
|
|
52
|
+
/** Filter state being edited in the open popup. */
|
|
53
|
+
this.pendingFilter = null;
|
|
54
|
+
/** Viewport-relative position for the filter popup. */
|
|
55
|
+
this.popupPos = { top: 0, left: 0 };
|
|
56
|
+
/** Current scroll offset of the scroll container — drives pagination footer. */
|
|
57
|
+
this.scrollTop = 0;
|
|
45
58
|
this.handleScroll = (e) => {
|
|
46
59
|
const scroller = e.currentTarget;
|
|
47
60
|
const scrollTop = scroller.scrollTop;
|
|
48
61
|
const total = this.totalElements;
|
|
49
62
|
const visStart = Math.floor(scrollTop / this.rowHeight);
|
|
50
63
|
const visEnd = Math.min(visStart + this.visibleCount(), total - 1);
|
|
64
|
+
this.scrollTop = scrollTop;
|
|
51
65
|
this.renderStart = Math.max(0, visStart - BUFFER);
|
|
52
66
|
this.renderEnd = Math.min(total - 1, visEnd + BUFFER);
|
|
53
67
|
this.requestPagesForWindow(this.renderStart, this.renderEnd);
|
|
54
68
|
};
|
|
55
69
|
}
|
|
70
|
+
// ── Prop watchers ─────────────────────────────────────────────────────────
|
|
71
|
+
/** Clamp renderEnd when totalElements shrinks (e.g. after a filter is applied). */
|
|
72
|
+
totalElementsChanged(newVal) {
|
|
73
|
+
this.renderEnd = Math.min(this.renderEnd, Math.max(0, newVal - 1));
|
|
74
|
+
}
|
|
56
75
|
// ── Public API ─────────────────────────────────────────────────────────────
|
|
57
76
|
/**
|
|
58
77
|
* Initialise (or reset) the virtual scroll.
|
|
@@ -69,7 +88,6 @@ export class MrdTable {
|
|
|
69
88
|
this.loadedPages = new Map();
|
|
70
89
|
this.requestedPages = new Set();
|
|
71
90
|
this.colWidths = [];
|
|
72
|
-
// Apply defaultSort prop as the initial sort state.
|
|
73
91
|
if (this.defaultSort) {
|
|
74
92
|
const parts = this.defaultSort.split(',');
|
|
75
93
|
this.sortField = parts[0].trim();
|
|
@@ -79,66 +97,105 @@ export class MrdTable {
|
|
|
79
97
|
this.sortField = '';
|
|
80
98
|
this.sortDir = 'asc';
|
|
81
99
|
}
|
|
100
|
+
this.scrollTop = 0;
|
|
82
101
|
this.renderStart = 0;
|
|
83
|
-
|
|
84
|
-
//
|
|
102
|
+
// No BUFFER on init — only request what fits the visible area (page 0).
|
|
103
|
+
// BUFFER is applied during scroll to pre-fetch the next page proactively.
|
|
104
|
+
this.renderEnd = Math.max(0, Math.min(this.visibleCount() - 1, this.totalElements - 1));
|
|
85
105
|
const scroller = this.el.querySelector('.mrd-table__scroll');
|
|
86
106
|
if (scroller)
|
|
87
107
|
scroller.scrollTop = 0;
|
|
88
|
-
// Do NOT emit mrdLoadPage here — the host injects page 0 via setPage().
|
|
89
108
|
}
|
|
90
109
|
/**
|
|
91
110
|
* Inject the rows for a given page (0-based).
|
|
92
111
|
* Creates a new Map reference so Stencil detects the state change.
|
|
112
|
+
*
|
|
113
|
+
* When the page contains fewer rows than pageSize it is the last page.
|
|
114
|
+
* renderEnd is clamped immediately so no loading-placeholder rows appear
|
|
115
|
+
* beyond the actual data — without requiring the host to update totalElements.
|
|
93
116
|
*/
|
|
94
117
|
async setPage(pageNumber, rows) {
|
|
118
|
+
if (rows.length < this.pageSize) {
|
|
119
|
+
// lastRowIdx is -1 when the page is empty; clamp renderEnd to -1 so the
|
|
120
|
+
// render loop does not execute and no shimmer rows appear.
|
|
121
|
+
const lastRowIdx = pageNumber * this.pageSize + rows.length - 1;
|
|
122
|
+
this.renderEnd = Math.min(this.renderEnd, lastRowIdx);
|
|
123
|
+
}
|
|
95
124
|
const next = new Map(this.loadedPages);
|
|
96
125
|
next.set(pageNumber, rows);
|
|
97
126
|
this.loadedPages = next;
|
|
98
127
|
}
|
|
99
|
-
// ──
|
|
128
|
+
// ── Lifecycle ──────────────────────────────────────────────────────────────
|
|
129
|
+
disconnectedCallback() {
|
|
130
|
+
if (this.outsideClickHandler) {
|
|
131
|
+
document.removeEventListener('click', this.outsideClickHandler);
|
|
132
|
+
this.outsideClickHandler = null;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
componentDidRender() {
|
|
136
|
+
if (this.colWidths.length === 0 && this.loadedPages.size > 0 && this.totalElements > 0) {
|
|
137
|
+
const ths = this.el.querySelectorAll('.mrd-table__header');
|
|
138
|
+
if (ths.length > 0) {
|
|
139
|
+
this.colWidths = Array.from(ths).map(th => th.offsetWidth);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// ── Paging / scroll helpers ────────────────────────────────────────────────
|
|
100
144
|
visibleCount() {
|
|
101
145
|
return Math.ceil(this.tableHeight / this.rowHeight);
|
|
102
146
|
}
|
|
103
|
-
/** Returns the current sort value for use in ?sort= query params. */
|
|
104
147
|
sortParam() {
|
|
105
148
|
if (!this.sortField)
|
|
106
149
|
return '';
|
|
107
150
|
return this.sortDir === 'desc' ? `${this.sortField},desc` : this.sortField;
|
|
108
151
|
}
|
|
109
|
-
/** Called when a header cell is clicked. Toggles direction or sets a new column. */
|
|
110
152
|
colName(col) {
|
|
111
153
|
var _a, _b, _c, _d;
|
|
112
154
|
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 : '';
|
|
113
155
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
// Cancel any pending scroll debounce.
|
|
156
|
+
colDataType(col) {
|
|
157
|
+
var _a, _b;
|
|
158
|
+
if (col.type === 'RELATION')
|
|
159
|
+
return 'RELATION';
|
|
160
|
+
return (_b = (_a = col.field) === null || _a === void 0 ? void 0 : _a.dataType) !== null && _b !== void 0 ? _b : 'TEXT';
|
|
161
|
+
}
|
|
162
|
+
/** Reset pagination state and scroll to top (used after sort or filter change). */
|
|
163
|
+
resetPages() {
|
|
124
164
|
if (this.debounceTimer !== null) {
|
|
125
165
|
clearTimeout(this.debounceTimer);
|
|
126
166
|
this.debounceTimer = null;
|
|
127
167
|
}
|
|
128
168
|
this.pendingPages.clear();
|
|
129
|
-
// Wipe all loaded data so the new sort order is fetched fresh.
|
|
130
169
|
this.loadedPages = new Map();
|
|
131
170
|
this.requestedPages = new Set();
|
|
132
171
|
this.colWidths = [];
|
|
172
|
+
this.scrollTop = 0;
|
|
133
173
|
this.renderStart = 0;
|
|
134
|
-
|
|
174
|
+
// No BUFFER here — totalElements may be stale after a filter change.
|
|
175
|
+
// Only request what is visible; BUFFER kicks in during scroll as usual.
|
|
176
|
+
this.renderEnd = Math.max(0, Math.min(this.visibleCount() - 1, this.totalElements - 1));
|
|
135
177
|
const scroller = this.el.querySelector('.mrd-table__scroll');
|
|
136
178
|
if (scroller)
|
|
137
179
|
scroller.scrollTop = 0;
|
|
138
|
-
|
|
180
|
+
}
|
|
181
|
+
handleSortClick(col) {
|
|
182
|
+
const name = this.colName(col);
|
|
183
|
+
if (this.sortField === name) {
|
|
184
|
+
this.sortDir = this.sortDir === 'asc' ? 'desc' : 'asc';
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
this.sortField = name;
|
|
188
|
+
this.sortDir = 'asc';
|
|
189
|
+
}
|
|
190
|
+
this.resetPages();
|
|
191
|
+
this.emitPagesForWindow(this.renderStart, this.renderEnd);
|
|
192
|
+
}
|
|
193
|
+
applySort(col, dir) {
|
|
194
|
+
this.sortField = this.colName(col);
|
|
195
|
+
this.sortDir = dir;
|
|
196
|
+
this.resetPages();
|
|
139
197
|
this.emitPagesForWindow(this.renderStart, this.renderEnd);
|
|
140
198
|
}
|
|
141
|
-
/** Emits mrdLoadPage immediately for all missing pages in [start, end]. */
|
|
142
199
|
emitPagesForWindow(start, end) {
|
|
143
200
|
const firstPage = Math.floor(start / this.pageSize);
|
|
144
201
|
const lastPage = Math.floor(end / this.pageSize);
|
|
@@ -171,13 +228,10 @@ export class MrdTable {
|
|
|
171
228
|
}
|
|
172
229
|
if (!anyNew)
|
|
173
230
|
return;
|
|
174
|
-
// Reset de timer: wacht tot het scrollen even stopt.
|
|
175
231
|
if (this.debounceTimer !== null)
|
|
176
232
|
clearTimeout(this.debounceTimer);
|
|
177
233
|
this.debounceTimer = setTimeout(() => this.flushPendingPages(), REQUEST_DEBOUNCE_MS);
|
|
178
234
|
}
|
|
179
|
-
/** Emitteert mrdLoadPage alleen voor pagina's die na de debounce-wachttijd
|
|
180
|
-
* nog steeds binnen het huidige render-venster vallen. */
|
|
181
235
|
flushPendingPages() {
|
|
182
236
|
this.debounceTimer = null;
|
|
183
237
|
if (this.pendingPages.size === 0)
|
|
@@ -185,10 +239,8 @@ export class MrdTable {
|
|
|
185
239
|
const next = new Set(this.requestedPages);
|
|
186
240
|
let changed = false;
|
|
187
241
|
for (const page of this.pendingPages) {
|
|
188
|
-
// Sla over als pagina inmiddels geladen of al aangevraagd is.
|
|
189
242
|
if (this.loadedPages.has(page) || next.has(page))
|
|
190
243
|
continue;
|
|
191
|
-
// Sla over als de pagina buiten het huidige venster is geraakt.
|
|
192
244
|
const pageStart = page * this.pageSize;
|
|
193
245
|
const pageEnd = pageStart + this.pageSize - 1;
|
|
194
246
|
if (pageEnd < this.renderStart || pageStart > this.renderEnd)
|
|
@@ -201,42 +253,236 @@ export class MrdTable {
|
|
|
201
253
|
if (changed)
|
|
202
254
|
this.requestedPages = next;
|
|
203
255
|
}
|
|
204
|
-
// ──
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
256
|
+
// ── Filter helpers ─────────────────────────────────────────────────────────
|
|
257
|
+
handleFilterToggle() {
|
|
258
|
+
this.filterMode = !this.filterMode;
|
|
259
|
+
if (!this.filterMode)
|
|
260
|
+
this.closeFilterPopup();
|
|
261
|
+
}
|
|
262
|
+
handleFilterOpen(col, e) {
|
|
263
|
+
e.stopPropagation();
|
|
264
|
+
const btn = e.currentTarget;
|
|
265
|
+
const rect = btn.getBoundingClientRect();
|
|
266
|
+
let left = rect.left;
|
|
267
|
+
if (left + POPUP_WIDTH > window.innerWidth - 8)
|
|
268
|
+
left = rect.right - POPUP_WIDTH;
|
|
269
|
+
this.popupPos = { top: rect.bottom + 4, left: Math.max(8, left) };
|
|
270
|
+
const name = this.colName(col);
|
|
271
|
+
const dataType = this.colDataType(col);
|
|
272
|
+
const existing = this.activeFilters.get(name);
|
|
273
|
+
this.pendingFilter = existing ? Object.assign({}, existing) : { field: name, dataType };
|
|
274
|
+
this.openFilterCol = name;
|
|
275
|
+
// Close on outside click — re-register to replace any stale handler
|
|
276
|
+
if (this.outsideClickHandler)
|
|
277
|
+
document.removeEventListener('click', this.outsideClickHandler);
|
|
278
|
+
this.outsideClickHandler = (ev) => {
|
|
279
|
+
const popup = this.el.querySelector('.mrd-table__filter-popup');
|
|
280
|
+
if (popup && !popup.contains(ev.target))
|
|
281
|
+
this.closeFilterPopup();
|
|
282
|
+
};
|
|
283
|
+
document.addEventListener('click', this.outsideClickHandler);
|
|
284
|
+
}
|
|
285
|
+
closeFilterPopup() {
|
|
286
|
+
this.openFilterCol = null;
|
|
287
|
+
this.pendingFilter = null;
|
|
288
|
+
if (this.outsideClickHandler) {
|
|
289
|
+
document.removeEventListener('click', this.outsideClickHandler);
|
|
290
|
+
this.outsideClickHandler = null;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
setPending(key, val) {
|
|
294
|
+
this.pendingFilter = Object.assign(Object.assign({}, this.pendingFilter), { [key]: val });
|
|
295
|
+
}
|
|
296
|
+
togglePendingValue(key, checked) {
|
|
297
|
+
var _a, _b;
|
|
298
|
+
const current = (_b = (_a = this.pendingFilter) === null || _a === void 0 ? void 0 : _a.values) !== null && _b !== void 0 ? _b : [];
|
|
299
|
+
this.pendingFilter = Object.assign(Object.assign({}, this.pendingFilter), { values: checked ? [...current, key] : current.filter(k => k !== key) });
|
|
300
|
+
}
|
|
301
|
+
filterHasValue(f) {
|
|
302
|
+
if (f.operator === 'isEmpty' || f.operator === 'isNotEmpty')
|
|
303
|
+
return true;
|
|
304
|
+
if (f.values !== undefined && f.values.length > 0)
|
|
305
|
+
return true;
|
|
306
|
+
if (f.value != null && f.value !== '')
|
|
307
|
+
return true;
|
|
308
|
+
if (typeof f.value === 'boolean')
|
|
309
|
+
return true;
|
|
310
|
+
if (f.from != null && f.from !== '')
|
|
311
|
+
return true;
|
|
312
|
+
if (f.to != null && f.to !== '')
|
|
313
|
+
return true;
|
|
314
|
+
return false;
|
|
315
|
+
}
|
|
316
|
+
applyFilter() {
|
|
317
|
+
const f = this.pendingFilter;
|
|
318
|
+
if (!(f === null || f === void 0 ? void 0 : f.field)) {
|
|
319
|
+
this.closeFilterPopup();
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
const next = new Map(this.activeFilters);
|
|
323
|
+
if (this.filterHasValue(f)) {
|
|
324
|
+
next.set(f.field, f);
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
next.delete(f.field);
|
|
328
|
+
}
|
|
329
|
+
this.activeFilters = next;
|
|
330
|
+
this.closeFilterPopup();
|
|
331
|
+
this.mrdFilter.emit({ filters: Array.from(this.activeFilters.values()) });
|
|
332
|
+
if (this.totalElements > 0) {
|
|
333
|
+
this.resetPages();
|
|
334
|
+
this.emitPagesForWindow(this.renderStart, this.renderEnd);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
clearFilter() {
|
|
338
|
+
const name = this.openFilterCol;
|
|
339
|
+
const next = new Map(this.activeFilters);
|
|
340
|
+
if (name)
|
|
341
|
+
next.delete(name);
|
|
342
|
+
this.activeFilters = next;
|
|
343
|
+
this.closeFilterPopup();
|
|
344
|
+
this.mrdFilter.emit({ filters: Array.from(this.activeFilters.values()) });
|
|
345
|
+
if (this.totalElements > 0) {
|
|
346
|
+
this.resetPages();
|
|
347
|
+
this.emitPagesForWindow(this.renderStart, this.renderEnd);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
clearAllFilters() {
|
|
351
|
+
this.activeFilters = new Map();
|
|
352
|
+
this.mrdFilter.emit({ filters: [] });
|
|
353
|
+
if (this.totalElements > 0) {
|
|
354
|
+
this.resetPages();
|
|
355
|
+
this.emitPagesForWindow(this.renderStart, this.renderEnd);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
// ── Render: toolbar ────────────────────────────────────────────────────────
|
|
359
|
+
renderToolbar() {
|
|
360
|
+
var _a;
|
|
361
|
+
const filterCount = this.activeFilters.size;
|
|
362
|
+
const hasActions = ((_a = this.actions) === null || _a === void 0 ? void 0 : _a.length) > 0;
|
|
363
|
+
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))))), hasActions && (h("div", { class: "mrd-table__toolbar-right" }, this.actions.map(a => {
|
|
364
|
+
var _a;
|
|
365
|
+
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
|
|
366
|
+
? h("svg", { class: "mrd-table__action-icon", "aria-hidden": "true" }, h("use", { href: a.icon }))
|
|
367
|
+
: a.label, h("span", { class: "mrd-table__action-tooltip" }, a.label)));
|
|
368
|
+
})))));
|
|
369
|
+
}
|
|
370
|
+
// ── Render: filter popup ───────────────────────────────────────────────────
|
|
371
|
+
renderFilterEditor(col) {
|
|
372
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
373
|
+
const pf = (_a = this.pendingFilter) !== null && _a !== void 0 ? _a : {};
|
|
374
|
+
const dataType = this.colDataType(col);
|
|
375
|
+
if (NO_FILTER_TYPES.has(dataType)) {
|
|
376
|
+
return h("p", { class: "mrd-table__filter-no-support" }, t('filter_no_support', this.locale));
|
|
377
|
+
}
|
|
378
|
+
if (dataType === 'BOOLEAN') {
|
|
379
|
+
return (h("div", { class: "mrd-table__filter-radio-group" }, [
|
|
380
|
+
{ labelKey: 'filter_all', value: null },
|
|
381
|
+
{ labelKey: 'yes', value: true },
|
|
382
|
+
{ labelKey: 'no', value: false },
|
|
383
|
+
].map(opt => (h("label", { class: "mrd-table__filter-radio-label" }, h("input", { type: "radio", name: `bf-${this.openFilterCol}`, checked: pf.value === opt.value, onChange: () => this.setPending('value', opt.value) }), t(opt.labelKey, this.locale))))));
|
|
213
384
|
}
|
|
385
|
+
if (dataType === 'LIST') {
|
|
386
|
+
const items = (_c = (_b = col.field) === null || _b === void 0 ? void 0 : _b.listItems) !== null && _c !== void 0 ? _c : [];
|
|
387
|
+
const selected = (_d = pf.values) !== null && _d !== void 0 ? _d : [];
|
|
388
|
+
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)))));
|
|
389
|
+
}
|
|
390
|
+
if (TEXT_TYPES.has(dataType) || dataType === 'RELATION') {
|
|
391
|
+
const op = (_e = pf.operator) !== null && _e !== void 0 ? _e : 'startsWith';
|
|
392
|
+
const noInput = op === 'isEmpty' || op === 'isNotEmpty';
|
|
393
|
+
return (h("div", { class: "mrd-table__filter-editor" }, h("select", { class: "mrd-table__filter-select", onChange: (e) => this.setPending('operator', e.target.value) }, [
|
|
394
|
+
{ val: 'startsWith', labelKey: 'filter_starts_with' },
|
|
395
|
+
{ val: 'equals', labelKey: 'filter_equals' },
|
|
396
|
+
{ val: 'isEmpty', labelKey: 'filter_is_empty' },
|
|
397
|
+
{ val: 'isNotEmpty', labelKey: 'filter_is_not_empty' },
|
|
398
|
+
].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) }))));
|
|
399
|
+
}
|
|
400
|
+
if (NUMERIC_TYPES.has(dataType)) {
|
|
401
|
+
const rangeMode = pf.from !== undefined || pf.to !== undefined;
|
|
402
|
+
return (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) })))));
|
|
403
|
+
}
|
|
404
|
+
if (DATE_TYPES.has(dataType)) {
|
|
405
|
+
const inputType = dataType === 'DATE' ? 'date'
|
|
406
|
+
: dataType === 'DATETIME' ? 'datetime-local'
|
|
407
|
+
: 'time';
|
|
408
|
+
const rangeMode = pf.from !== undefined || pf.to !== undefined;
|
|
409
|
+
return (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) })))));
|
|
410
|
+
}
|
|
411
|
+
return null;
|
|
412
|
+
}
|
|
413
|
+
renderFilterPopup() {
|
|
414
|
+
var _a, _b, _c, _d;
|
|
415
|
+
if (!this.openFilterCol || !this.pendingFilter)
|
|
416
|
+
return null;
|
|
417
|
+
const col = this.columns.find(c => this.colName(c) === this.openFilterCol);
|
|
418
|
+
if (!col)
|
|
419
|
+
return null;
|
|
420
|
+
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;
|
|
421
|
+
const sortActive = this.sortField === this.openFilterCol;
|
|
422
|
+
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)))));
|
|
423
|
+
}
|
|
424
|
+
// ── Render: footer ────────────────────────────────────────────────────────
|
|
425
|
+
renderFooter(rowCount, effectiveTotal) {
|
|
426
|
+
const total = this.totalElements;
|
|
427
|
+
// Non-paginated mode: show plain row count
|
|
428
|
+
if (total === 0) {
|
|
429
|
+
const count = rowCount !== null && rowCount !== void 0 ? rowCount : 0;
|
|
430
|
+
if (count === 0)
|
|
431
|
+
return null;
|
|
432
|
+
return (h("div", { class: "mrd-table__footer" }, count, " ", t('table_of', this.locale), " ", count));
|
|
433
|
+
}
|
|
434
|
+
// Paginated mode: only show once page 0 has loaded (avoids stale total during filter reset)
|
|
435
|
+
if (!this.loadedPages.has(0))
|
|
436
|
+
return null;
|
|
437
|
+
// Use effectiveTotal (derived from actual page lengths) so the counter
|
|
438
|
+
// is correct even when the host has not yet updated totalElements.
|
|
439
|
+
const displayTotal = effectiveTotal !== null && effectiveTotal !== void 0 ? effectiveTotal : total;
|
|
440
|
+
// Compute from/to independently so partial rows at top/bottom are included.
|
|
441
|
+
const from = Math.min(Math.floor(this.scrollTop / this.rowHeight) + 1, displayTotal);
|
|
442
|
+
const to = Math.min(Math.ceil((this.scrollTop + this.tableHeight) / this.rowHeight), displayTotal);
|
|
443
|
+
return (h("div", { class: "mrd-table__footer" }, from, "\u2013", to, " ", t('table_of', this.locale), " ", displayTotal));
|
|
214
444
|
}
|
|
215
445
|
// ── Render ─────────────────────────────────────────────────────────────────
|
|
216
446
|
render() {
|
|
217
|
-
var _a, _b;
|
|
447
|
+
var _a, _b, _c;
|
|
218
448
|
if (!((_a = this.columns) === null || _a === void 0 ? void 0 : _a.length))
|
|
219
449
|
return null;
|
|
220
450
|
const numericTypes = new Set(['INTEGER', 'DECIMAL', 'PERCENTAGE', 'CURRENCY']);
|
|
221
451
|
// ── Non-paginated mode ──────────────────────────────────────────────────
|
|
222
452
|
if (this.totalElements === 0) {
|
|
223
|
-
return (h(Host, null, h("div", { class: "mrd-table" }, h("table", { class: "mrd-table__table" }, h("thead", null, h("tr", null, this.columns.map(col => {
|
|
453
|
+
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 => {
|
|
224
454
|
var _a, _b, _c, _d;
|
|
225
|
-
|
|
455
|
+
const name = this.colName(col);
|
|
456
|
+
const isFiltered = this.activeFilters.has(name);
|
|
457
|
+
return (h("th", { class: `mrd-table__header${isFiltered ? ' mrd-table__header--filtered' : ''}` }, 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 : ''), this.filterMode && (h("button", { class: `mrd-table__header-filter-btn${isFiltered ? ' mrd-table__header-filter-btn--active' : ''}`, onClick: (e) => this.handleFilterOpen(col, e) }, "\u25BE"))));
|
|
226
458
|
}))), 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 => {
|
|
227
459
|
var _a, _b;
|
|
228
460
|
const value = CellRenderer.render(col, row, this.locale);
|
|
229
461
|
const isNumeric = col.type === 'FIELD' && numericTypes.has((_b = (_a = col.field) === null || _a === void 0 ? void 0 : _a.dataType) !== null && _b !== void 0 ? _b : '');
|
|
230
462
|
return (h("td", { class: `mrd-table__cell${isNumeric ? ' mrd-table__cell--numeric' : ''}` }, value));
|
|
231
|
-
})))))), (!this.rows || this.rows.length === 0) && (h("p", { class: "mrd-table__empty" },
|
|
463
|
+
})))))), (!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()));
|
|
232
464
|
}
|
|
233
465
|
// ── Paginated / virtual-scroll mode ────────────────────────────────────
|
|
234
|
-
|
|
466
|
+
// Derive the authoritative row count from loaded pages:
|
|
467
|
+
// if any loaded page is shorter than pageSize it is the last page,
|
|
468
|
+
// so the true total cannot exceed (pageNum * pageSize + pageRows.length).
|
|
469
|
+
// This self-corrects without requiring the host to update totalElements.
|
|
470
|
+
let effectiveTotal = this.totalElements;
|
|
471
|
+
for (const [pageNum, pageRows] of this.loadedPages) {
|
|
472
|
+
if (pageRows.length < this.pageSize) {
|
|
473
|
+
effectiveTotal = Math.min(effectiveTotal, pageNum * this.pageSize + pageRows.length);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
// Clamp renderEnd to what we actually know exists (-1 when empty)
|
|
477
|
+
const clampedEnd = Math.min(this.renderEnd, effectiveTotal - 1);
|
|
235
478
|
const colCount = this.columns.length;
|
|
236
479
|
const topSpacerHeight = this.renderStart * this.rowHeight;
|
|
237
|
-
const bottomSpacerHeight = Math.max(0, (
|
|
480
|
+
const bottomSpacerHeight = Math.max(0, (effectiveTotal - 1 - clampedEnd) * this.rowHeight);
|
|
481
|
+
const tableStyle = this.colWidths.length > 0
|
|
482
|
+
? { tableLayout: 'fixed' }
|
|
483
|
+
: undefined;
|
|
238
484
|
const renderedRows = [];
|
|
239
|
-
for (let i = this.renderStart; i <=
|
|
485
|
+
for (let i = this.renderStart; i <= clampedEnd; i++) {
|
|
240
486
|
const row = this.getRow(i);
|
|
241
487
|
if (row === null) {
|
|
242
488
|
renderedRows.push(h("tr", { class: "mrd-table__row mrd-table__row--loading" }, h("td", { class: "mrd-table__cell--placeholder", colSpan: colCount }, h("span", { class: "mrd-table__placeholder-bar" }))));
|
|
@@ -250,15 +496,19 @@ export class MrdTable {
|
|
|
250
496
|
})));
|
|
251
497
|
}
|
|
252
498
|
}
|
|
253
|
-
|
|
254
|
-
? { tableLayout: 'fixed' }
|
|
255
|
-
: undefined;
|
|
256
|
-
return (h(Host, null, 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) => {
|
|
499
|
+
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) => {
|
|
257
500
|
var _a, _b, _c, _d;
|
|
258
|
-
const
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
501
|
+
const name = this.colName(col);
|
|
502
|
+
const isActive = this.sortField === name;
|
|
503
|
+
const isFiltered = this.activeFilters.has(name);
|
|
504
|
+
const cls = [
|
|
505
|
+
'mrd-table__header',
|
|
506
|
+
'mrd-table__header--sortable',
|
|
507
|
+
isActive ? `mrd-table__header--sorted-${this.sortDir}` : '',
|
|
508
|
+
isFiltered ? 'mrd-table__header--filtered' : '',
|
|
509
|
+
].filter(Boolean).join(' ');
|
|
510
|
+
return (h("th", { class: cls, style: this.colWidths[idx] ? { width: `${this.colWidths[idx]}px` } : undefined, onClick: () => this.handleSortClick(col) }, 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 : ''), h("span", { class: "mrd-table__sort-icon", "aria-hidden": "true" }, isActive ? (this.sortDir === 'asc' ? '▲' : '▼') : '⇅'), this.filterMode && (h("button", { class: `mrd-table__header-filter-btn${isFiltered ? ' mrd-table__header-filter-btn--active' : ''}`, onClick: (e) => { e.stopPropagation(); this.handleFilterOpen(col, e); } }, "\u25BE"))));
|
|
511
|
+
}))), 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 })))))), 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()));
|
|
262
512
|
}
|
|
263
513
|
static get is() { return "mrd-table"; }
|
|
264
514
|
static get encapsulation() { return "scoped"; }
|
|
@@ -441,6 +691,31 @@ export class MrdTable {
|
|
|
441
691
|
"reflect": false,
|
|
442
692
|
"attribute": "default-sort",
|
|
443
693
|
"defaultValue": "''"
|
|
694
|
+
},
|
|
695
|
+
"actions": {
|
|
696
|
+
"type": "unknown",
|
|
697
|
+
"mutable": false,
|
|
698
|
+
"complexType": {
|
|
699
|
+
"original": "TableAction[]",
|
|
700
|
+
"resolved": "TableAction[]",
|
|
701
|
+
"references": {
|
|
702
|
+
"TableAction": {
|
|
703
|
+
"location": "import",
|
|
704
|
+
"path": "../../utils/cell-renderer",
|
|
705
|
+
"id": "src/utils/cell-renderer.ts::TableAction",
|
|
706
|
+
"referenceLocation": "TableAction"
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
},
|
|
710
|
+
"required": false,
|
|
711
|
+
"optional": false,
|
|
712
|
+
"docs": {
|
|
713
|
+
"tags": [],
|
|
714
|
+
"text": "Toolbar action buttons rendered above the table."
|
|
715
|
+
},
|
|
716
|
+
"getter": false,
|
|
717
|
+
"setter": false,
|
|
718
|
+
"defaultValue": "[]"
|
|
444
719
|
}
|
|
445
720
|
};
|
|
446
721
|
}
|
|
@@ -452,7 +727,13 @@ export class MrdTable {
|
|
|
452
727
|
"renderEnd": {},
|
|
453
728
|
"colWidths": {},
|
|
454
729
|
"sortField": {},
|
|
455
|
-
"sortDir": {}
|
|
730
|
+
"sortDir": {},
|
|
731
|
+
"filterMode": {},
|
|
732
|
+
"activeFilters": {},
|
|
733
|
+
"openFilterCol": {},
|
|
734
|
+
"pendingFilter": {},
|
|
735
|
+
"popupPos": {},
|
|
736
|
+
"scrollTop": {}
|
|
456
737
|
};
|
|
457
738
|
}
|
|
458
739
|
static get events() {
|
|
@@ -491,6 +772,43 @@ export class MrdTable {
|
|
|
491
772
|
}
|
|
492
773
|
}
|
|
493
774
|
}
|
|
775
|
+
}, {
|
|
776
|
+
"method": "mrdAction",
|
|
777
|
+
"name": "mrdAction",
|
|
778
|
+
"bubbles": true,
|
|
779
|
+
"cancelable": true,
|
|
780
|
+
"composed": true,
|
|
781
|
+
"docs": {
|
|
782
|
+
"tags": [],
|
|
783
|
+
"text": "Fired when a toolbar action button is clicked. Detail contains the action identifier."
|
|
784
|
+
},
|
|
785
|
+
"complexType": {
|
|
786
|
+
"original": "{ action: string }",
|
|
787
|
+
"resolved": "{ action: string; }",
|
|
788
|
+
"references": {}
|
|
789
|
+
}
|
|
790
|
+
}, {
|
|
791
|
+
"method": "mrdFilter",
|
|
792
|
+
"name": "mrdFilter",
|
|
793
|
+
"bubbles": true,
|
|
794
|
+
"cancelable": true,
|
|
795
|
+
"composed": true,
|
|
796
|
+
"docs": {
|
|
797
|
+
"tags": [],
|
|
798
|
+
"text": "Fired when active filters change. Host translates filters to API query params."
|
|
799
|
+
},
|
|
800
|
+
"complexType": {
|
|
801
|
+
"original": "{ filters: ColumnFilter[] }",
|
|
802
|
+
"resolved": "{ filters: ColumnFilter[]; }",
|
|
803
|
+
"references": {
|
|
804
|
+
"ColumnFilter": {
|
|
805
|
+
"location": "import",
|
|
806
|
+
"path": "../../utils/cell-renderer",
|
|
807
|
+
"id": "src/utils/cell-renderer.ts::ColumnFilter",
|
|
808
|
+
"referenceLocation": "ColumnFilter"
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
}
|
|
494
812
|
}];
|
|
495
813
|
}
|
|
496
814
|
static get methods() {
|
|
@@ -541,11 +859,17 @@ export class MrdTable {
|
|
|
541
859
|
"return": "Promise<void>"
|
|
542
860
|
},
|
|
543
861
|
"docs": {
|
|
544
|
-
"text": "Inject the rows for a given page (0-based).\nCreates a new Map reference so Stencil detects the state change.",
|
|
862
|
+
"text": "Inject the rows for a given page (0-based).\nCreates a new Map reference so Stencil detects the state change.\n\nWhen the page contains fewer rows than pageSize it is the last page.\nrenderEnd is clamped immediately so no loading-placeholder rows appear\nbeyond the actual data \u2014 without requiring the host to update totalElements.",
|
|
545
863
|
"tags": []
|
|
546
864
|
}
|
|
547
865
|
}
|
|
548
866
|
};
|
|
549
867
|
}
|
|
550
868
|
static get elementRef() { return "el"; }
|
|
869
|
+
static get watchers() {
|
|
870
|
+
return [{
|
|
871
|
+
"propName": "totalElements",
|
|
872
|
+
"methodName": "totalElementsChanged"
|
|
873
|
+
}];
|
|
874
|
+
}
|
|
551
875
|
}
|