@mmlogic/components 0.1.14 → 0.1.16
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/dist/cjs/{format-BT6-_W7X.js → format-IFzg0q-6.js} +13 -1
- 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 +53 -20
- package/dist/cjs/mrd-table.cjs.entry.js +134 -15
- package/dist/collection/components/mrd-field/mrd-field.js +2 -2
- package/dist/collection/components/mrd-form/mrd-form.js +53 -20
- package/dist/collection/components/mrd-relation-field/mrd-relation-field.js +3 -3
- package/dist/collection/components/mrd-table/mrd-table.js +134 -14
- package/dist/collection/components/mrd-table/mrd-table.scss +88 -27
- package/dist/collection/dev/app.js +8 -6
- package/dist/collection/utils/format.js +1 -1
- package/dist/collection/utils/i18n.js +12 -0
- package/dist/components/format.js +1 -1
- package/dist/components/i18n.js +1 -1
- package/dist/components/mrd-form.js +1 -1
- package/dist/components/mrd-relation-field2.js +1 -1
- package/dist/components/mrd-table.js +1 -1
- package/dist/esm/{format-beKIX2qZ.js → format-Cc9kQ1j-.js} +13 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/mosterdcomponents.js +1 -1
- package/dist/esm/mrd-boolean-field_16.entry.js +53 -20
- package/dist/esm/mrd-table.entry.js +134 -15
- package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
- package/dist/mosterdcomponents/p-1e0d88fd.entry.js +1 -0
- package/dist/mosterdcomponents/p-829b9b6f.entry.js +1 -0
- package/dist/mosterdcomponents/p-Cc9kQ1j-.js +1 -0
- package/dist/types/components/mrd-field/mrd-field.d.ts +1 -0
- package/dist/types/components/mrd-form/mrd-form.d.ts +9 -4
- package/dist/types/components/mrd-relation-field/mrd-relation-field.d.ts +1 -0
- package/dist/types/components/mrd-table/mrd-table.d.ts +11 -0
- package/dist/types/components.d.ts +6 -6
- package/package.json +1 -1
- package/dist/mosterdcomponents/p-33e56d76.entry.js +0 -1
- package/dist/mosterdcomponents/p-80d6eff2.entry.js +0 -1
- package/dist/mosterdcomponents/p-beKIX2qZ.js +0 -1
|
@@ -30,6 +30,7 @@ export class MrdForm {
|
|
|
30
30
|
this.formValues = {};
|
|
31
31
|
this.errors = {};
|
|
32
32
|
this.submitted = false;
|
|
33
|
+
this.initialValues = {};
|
|
33
34
|
this.handleFieldChange = (e) => {
|
|
34
35
|
const { name, value } = e.detail;
|
|
35
36
|
const prevHref = this.getHref(this.formValues[name]);
|
|
@@ -80,8 +81,9 @@ export class MrdForm {
|
|
|
80
81
|
};
|
|
81
82
|
}
|
|
82
83
|
componentWillLoad() {
|
|
83
|
-
var _a;
|
|
84
|
-
this.
|
|
84
|
+
var _a, _b;
|
|
85
|
+
this.initialValues = Object.assign({}, ((_a = this.values) !== null && _a !== void 0 ? _a : {}));
|
|
86
|
+
this.formValues = Object.assign({}, ((_b = this.values) !== null && _b !== void 0 ? _b : {}));
|
|
85
87
|
}
|
|
86
88
|
componentDidLoad() {
|
|
87
89
|
// Apply reference pre-fill and emit mrdFetchAll for dependent DROPDOWN fields.
|
|
@@ -94,6 +96,7 @@ export class MrdForm {
|
|
|
94
96
|
/** Sync formValues when the values prop is set from outside after mount
|
|
95
97
|
* (e.g. when pre-filling an existing record in edit mode). */
|
|
96
98
|
valuesChanged(newValues) {
|
|
99
|
+
this.initialValues = Object.assign({}, (newValues !== null && newValues !== void 0 ? newValues : {}));
|
|
97
100
|
this.formValues = Object.assign({}, (newValues !== null && newValues !== void 0 ? newValues : {}));
|
|
98
101
|
this.applyReferenceValue();
|
|
99
102
|
this.errors = {};
|
|
@@ -221,10 +224,42 @@ export class MrdForm {
|
|
|
221
224
|
this.errors = newErrors;
|
|
222
225
|
return Object.keys(newErrors).length === 0;
|
|
223
226
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
227
|
+
normalizeFieldValue(value) {
|
|
228
|
+
return (value === '' || value == null) ? null : value;
|
|
229
|
+
}
|
|
230
|
+
normalizeRelationValue(value) {
|
|
231
|
+
if (value == null || value === '')
|
|
232
|
+
return null;
|
|
233
|
+
if (typeof value === 'string')
|
|
234
|
+
return value || null;
|
|
235
|
+
if (Array.isArray(value)) {
|
|
236
|
+
return value.map(v => typeof v === 'object' && v !== null && 'id' in v ? v.id : String(v));
|
|
237
|
+
}
|
|
238
|
+
if (typeof value === 'object' && 'id' in value) {
|
|
239
|
+
return value.id || null;
|
|
240
|
+
}
|
|
241
|
+
return null;
|
|
242
|
+
}
|
|
243
|
+
deepEqual(a, b) {
|
|
244
|
+
if (a === b)
|
|
245
|
+
return true;
|
|
246
|
+
if (a == null && b == null)
|
|
247
|
+
return true;
|
|
248
|
+
if (a == null || b == null)
|
|
249
|
+
return false;
|
|
250
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
251
|
+
if (a.length !== b.length)
|
|
252
|
+
return false;
|
|
253
|
+
const sa = [...a].sort();
|
|
254
|
+
const sb = [...b].sort();
|
|
255
|
+
return JSON.stringify(sa) === JSON.stringify(sb);
|
|
256
|
+
}
|
|
257
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
258
|
+
}
|
|
259
|
+
/** Build a submit payload containing only fields that changed relative to
|
|
260
|
+
* initialValues. For a new record (POST) initialValues is empty, so every
|
|
261
|
+
* non-null field is included. For edit (PATCH) only modified fields are sent,
|
|
262
|
+
* including fields explicitly cleared to null.
|
|
228
263
|
*/
|
|
229
264
|
buildSubmitPayload() {
|
|
230
265
|
var _a, _b;
|
|
@@ -234,23 +269,21 @@ export class MrdForm {
|
|
|
234
269
|
if (item.type === ClientLayoutItemType.FIELD && item.field) {
|
|
235
270
|
const name = item.field.name;
|
|
236
271
|
const value = this.formValues[name];
|
|
237
|
-
// Skip file/image fields that are still uploading (value is a File object)
|
|
238
272
|
if (value instanceof File)
|
|
239
273
|
continue;
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
274
|
+
const current = this.normalizeFieldValue(value);
|
|
275
|
+
const initial = this.normalizeFieldValue(this.initialValues[name]);
|
|
276
|
+
if (this.deepEqual(current, initial))
|
|
277
|
+
continue;
|
|
278
|
+
payload[name] = current;
|
|
243
279
|
}
|
|
244
280
|
else if (item.type === ClientLayoutItemType.RELATION && item.relation) {
|
|
245
281
|
const name = item.relation.name;
|
|
246
|
-
const
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
else if (value !== '' && value !== undefined) {
|
|
252
|
-
payload[name] = value !== null && value !== void 0 ? value : null;
|
|
253
|
-
}
|
|
282
|
+
const current = this.normalizeRelationValue(this.formValues[name]);
|
|
283
|
+
const initial = this.normalizeRelationValue(this.initialValues[name]);
|
|
284
|
+
if (this.deepEqual(current, initial))
|
|
285
|
+
continue;
|
|
286
|
+
payload[name] = current;
|
|
254
287
|
}
|
|
255
288
|
}
|
|
256
289
|
return payload;
|
|
@@ -473,8 +506,8 @@ export class MrdForm {
|
|
|
473
506
|
"text": ""
|
|
474
507
|
},
|
|
475
508
|
"complexType": {
|
|
476
|
-
"original": "{ query: string; relatedClass: string }",
|
|
477
|
-
"resolved": "{ query: string; relatedClass: string; }",
|
|
509
|
+
"original": "{ name: string; query: string; relatedClass: string }",
|
|
510
|
+
"resolved": "{ name: string; query: string; relatedClass: string; }",
|
|
478
511
|
"references": {}
|
|
479
512
|
}
|
|
480
513
|
}, {
|
|
@@ -70,7 +70,7 @@ export class MrdRelationField {
|
|
|
70
70
|
this.isLoading = true;
|
|
71
71
|
this.showResults = true;
|
|
72
72
|
this.searchDebounce = setTimeout(() => {
|
|
73
|
-
this.mrdSearch.emit({ query, relatedClass: this.mostSignificantClass });
|
|
73
|
+
this.mrdSearch.emit({ name: this.name, query, relatedClass: this.mostSignificantClass });
|
|
74
74
|
}, 300);
|
|
75
75
|
}
|
|
76
76
|
else {
|
|
@@ -543,8 +543,8 @@ export class MrdRelationField {
|
|
|
543
543
|
"text": ""
|
|
544
544
|
},
|
|
545
545
|
"complexType": {
|
|
546
|
-
"original": "{ query: string; relatedClass: string }",
|
|
547
|
-
"resolved": "{ query: string; relatedClass: string; }",
|
|
546
|
+
"original": "{ name: string; query: string; relatedClass: string }",
|
|
547
|
+
"resolved": "{ name: string; query: string; relatedClass: string; }",
|
|
548
548
|
"references": {}
|
|
549
549
|
}
|
|
550
550
|
}, {
|
|
@@ -17,6 +17,7 @@ export class MrdTable {
|
|
|
17
17
|
this.pendingPages = new Set();
|
|
18
18
|
this.debounceTimer = null;
|
|
19
19
|
this.outsideClickHandler = null;
|
|
20
|
+
this.keydownHandler = null;
|
|
20
21
|
// ── Props ──────────────────────────────────────────────────────────────────
|
|
21
22
|
this.columns = [];
|
|
22
23
|
/** Direct rows (non-paginated mode, used when totalElements === 0). */
|
|
@@ -55,6 +56,8 @@ export class MrdTable {
|
|
|
55
56
|
this.popupPos = { top: 0, left: 0 };
|
|
56
57
|
/** Current scroll offset of the scroll container — drives pagination footer. */
|
|
57
58
|
this.scrollTop = 0;
|
|
59
|
+
/** Full text shown in the TEXTBLOCK expand modal (null = closed). */
|
|
60
|
+
this.textblockModal = null;
|
|
58
61
|
this.handleScroll = (e) => {
|
|
59
62
|
const scroller = e.currentTarget;
|
|
60
63
|
const scrollTop = scroller.scrollTop;
|
|
@@ -131,6 +134,10 @@ export class MrdTable {
|
|
|
131
134
|
document.removeEventListener('click', this.outsideClickHandler);
|
|
132
135
|
this.outsideClickHandler = null;
|
|
133
136
|
}
|
|
137
|
+
if (this.keydownHandler) {
|
|
138
|
+
document.removeEventListener('keydown', this.keydownHandler);
|
|
139
|
+
this.keydownHandler = null;
|
|
140
|
+
}
|
|
134
141
|
}
|
|
135
142
|
componentDidRender() {
|
|
136
143
|
if (this.colWidths.length === 0 && this.loadedPages.size > 0 && this.totalElements > 0) {
|
|
@@ -275,7 +282,26 @@ export class MrdTable {
|
|
|
275
282
|
const defaultOperator = (TEXT_TYPES.has(dataType) || dataType === 'RELATION')
|
|
276
283
|
? 'startsWith'
|
|
277
284
|
: undefined;
|
|
278
|
-
|
|
285
|
+
// For DATETIME, stored values are UTC ISO strings; convert back to local
|
|
286
|
+
// "YYYY-MM-DD" dates so the date inputs show what the user originally entered.
|
|
287
|
+
// If from and to cover the same local day it was an exact-date filter — restore
|
|
288
|
+
// to exact mode so the user sees the single-date input again.
|
|
289
|
+
if (dataType === 'DATETIME' && existing) {
|
|
290
|
+
const display = Object.assign({}, existing);
|
|
291
|
+
if (typeof display.from === 'string' && display.from)
|
|
292
|
+
display.from = this.utcISOToLocalDate(display.from);
|
|
293
|
+
if (typeof display.to === 'string' && display.to)
|
|
294
|
+
display.to = this.utcISOToLocalDateExclusiveEnd(display.to);
|
|
295
|
+
if (display.from && display.to && display.from === display.to) {
|
|
296
|
+
this.pendingFilter = Object.assign(Object.assign({}, display), { value: display.from, from: undefined, to: undefined });
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
this.pendingFilter = display;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
this.pendingFilter = existing ? Object.assign({}, existing) : { field: name, dataType, operator: defaultOperator };
|
|
304
|
+
}
|
|
279
305
|
this.openFilterCol = name;
|
|
280
306
|
// Close on outside click — re-register to replace any stale handler
|
|
281
307
|
if (this.outsideClickHandler)
|
|
@@ -295,6 +321,23 @@ export class MrdTable {
|
|
|
295
321
|
this.outsideClickHandler = null;
|
|
296
322
|
}
|
|
297
323
|
}
|
|
324
|
+
openTextblockModal(text) {
|
|
325
|
+
this.textblockModal = text;
|
|
326
|
+
if (this.keydownHandler)
|
|
327
|
+
document.removeEventListener('keydown', this.keydownHandler);
|
|
328
|
+
this.keydownHandler = (ev) => {
|
|
329
|
+
if (ev.key === 'Escape')
|
|
330
|
+
this.closeTextblockModal();
|
|
331
|
+
};
|
|
332
|
+
document.addEventListener('keydown', this.keydownHandler);
|
|
333
|
+
}
|
|
334
|
+
closeTextblockModal() {
|
|
335
|
+
this.textblockModal = null;
|
|
336
|
+
if (this.keydownHandler) {
|
|
337
|
+
document.removeEventListener('keydown', this.keydownHandler);
|
|
338
|
+
this.keydownHandler = null;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
298
341
|
setPending(key, val) {
|
|
299
342
|
this.pendingFilter = Object.assign(Object.assign({}, this.pendingFilter), { [key]: val });
|
|
300
343
|
}
|
|
@@ -318,18 +361,70 @@ export class MrdTable {
|
|
|
318
361
|
return true;
|
|
319
362
|
return false;
|
|
320
363
|
}
|
|
364
|
+
// Convert a local "YYYY-MM-DD" date string to the UTC ISO string at the
|
|
365
|
+
// start of that local day (midnight). new Date(y, m, d) uses local time.
|
|
366
|
+
dateLocalToUTCStart(dateStr) {
|
|
367
|
+
if (!dateStr)
|
|
368
|
+
return dateStr;
|
|
369
|
+
const [year, month, day] = dateStr.split('-').map(Number);
|
|
370
|
+
return new Date(year, month - 1, day).toISOString().replace(/\.\d{3}Z$/, 'Z');
|
|
371
|
+
}
|
|
372
|
+
// Start of the day AFTER the given local date (exclusive range end).
|
|
373
|
+
dateLocalToUTCEndExclusive(dateStr) {
|
|
374
|
+
if (!dateStr)
|
|
375
|
+
return dateStr;
|
|
376
|
+
const [year, month, day] = dateStr.split('-').map(Number);
|
|
377
|
+
return new Date(year, month - 1, day + 1).toISOString().replace(/\.\d{3}Z$/, 'Z');
|
|
378
|
+
}
|
|
379
|
+
// Convert a stored UTC ISO string back to the local "YYYY-MM-DD" date.
|
|
380
|
+
utcISOToLocalDate(utcStr) {
|
|
381
|
+
if (!utcStr)
|
|
382
|
+
return utcStr;
|
|
383
|
+
const d = new Date(utcStr);
|
|
384
|
+
if (isNaN(d.getTime()))
|
|
385
|
+
return utcStr;
|
|
386
|
+
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
|
|
387
|
+
}
|
|
388
|
+
// The stored "to" value is the exclusive end (midnight of the next day).
|
|
389
|
+
// Subtract one day to recover the local date the user entered.
|
|
390
|
+
utcISOToLocalDateExclusiveEnd(utcStr) {
|
|
391
|
+
if (!utcStr)
|
|
392
|
+
return utcStr;
|
|
393
|
+
const d = new Date(utcStr);
|
|
394
|
+
if (isNaN(d.getTime()))
|
|
395
|
+
return utcStr;
|
|
396
|
+
d.setDate(d.getDate() - 1);
|
|
397
|
+
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
|
|
398
|
+
}
|
|
321
399
|
applyFilter() {
|
|
322
400
|
const f = this.pendingFilter;
|
|
323
401
|
if (!(f === null || f === void 0 ? void 0 : f.field)) {
|
|
324
402
|
this.closeFilterPopup();
|
|
325
403
|
return;
|
|
326
404
|
}
|
|
405
|
+
// For DATETIME fields the user enters local dates; convert to UTC ISO strings.
|
|
406
|
+
// Exact date → range covering the full local day (from = midnight, to = next midnight).
|
|
407
|
+
// "to" is always the exclusive end (midnight of the next local day).
|
|
408
|
+
let normalized = Object.assign({}, f);
|
|
409
|
+
if (f.dataType === 'DATETIME') {
|
|
410
|
+
if (typeof normalized.value === 'string' && normalized.value) {
|
|
411
|
+
normalized.from = this.dateLocalToUTCStart(normalized.value);
|
|
412
|
+
normalized.to = this.dateLocalToUTCEndExclusive(normalized.value);
|
|
413
|
+
normalized.value = undefined;
|
|
414
|
+
}
|
|
415
|
+
else {
|
|
416
|
+
if (typeof normalized.from === 'string' && normalized.from)
|
|
417
|
+
normalized.from = this.dateLocalToUTCStart(normalized.from);
|
|
418
|
+
if (typeof normalized.to === 'string' && normalized.to)
|
|
419
|
+
normalized.to = this.dateLocalToUTCEndExclusive(normalized.to);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
327
422
|
const next = new Map(this.activeFilters);
|
|
328
|
-
if (this.filterHasValue(
|
|
329
|
-
next.set(
|
|
423
|
+
if (this.filterHasValue(normalized)) {
|
|
424
|
+
next.set(normalized.field, normalized);
|
|
330
425
|
}
|
|
331
426
|
else {
|
|
332
|
-
next.delete(
|
|
427
|
+
next.delete(normalized.field);
|
|
333
428
|
}
|
|
334
429
|
this.activeFilters = next;
|
|
335
430
|
this.closeFilterPopup();
|
|
@@ -374,7 +469,7 @@ export class MrdTable {
|
|
|
374
469
|
}
|
|
375
470
|
// ── Render: filter popup ───────────────────────────────────────────────────
|
|
376
471
|
renderFilterEditor(col) {
|
|
377
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
472
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
378
473
|
const pf = (_a = this.pendingFilter) !== null && _a !== void 0 ? _a : {};
|
|
379
474
|
const dataType = this.colDataType(col);
|
|
380
475
|
if (NO_FILTER_TYPES.has(dataType)) {
|
|
@@ -406,12 +501,14 @@ export class MrdTable {
|
|
|
406
501
|
const rangeMode = pf.from !== undefined || pf.to !== undefined;
|
|
407
502
|
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) })))));
|
|
408
503
|
}
|
|
504
|
+
if (dataType === 'DATETIME') {
|
|
505
|
+
const rangeMode = pf.from !== undefined || pf.to !== undefined;
|
|
506
|
+
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: "date", class: "mrd-table__filter-input", value: String((_g = pf.value) !== null && _g !== void 0 ? _g : ''), onInput: (e) => this.setPending('value', e.target.value) })) : (h("div", { class: "mrd-table__filter-range mrd-table__filter-range--stacked" }, h("label", { class: "mrd-table__filter-range-label" }, t('filter_from', this.locale)), h("input", { type: "date", class: "mrd-table__filter-input", value: pf.from != null ? String(pf.from) : '', onInput: (e) => this.setPending('from', e.target.value) }), h("label", { class: "mrd-table__filter-range-label" }, t('filter_to', this.locale)), h("input", { type: "date", class: "mrd-table__filter-input", value: pf.to != null ? String(pf.to) : '', onInput: (e) => this.setPending('to', e.target.value) })))));
|
|
507
|
+
}
|
|
409
508
|
if (DATE_TYPES.has(dataType)) {
|
|
410
|
-
const inputType = dataType === 'DATE' ? 'date'
|
|
411
|
-
: dataType === 'DATETIME' ? 'datetime-local'
|
|
412
|
-
: 'time';
|
|
509
|
+
const inputType = dataType === 'DATE' ? 'date' : 'time';
|
|
413
510
|
const rangeMode = pf.from !== undefined || pf.to !== undefined;
|
|
414
|
-
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((
|
|
511
|
+
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((_h = pf.value) !== null && _h !== void 0 ? _h : ''), onInput: (e) => this.setPending('value', e.target.value) })) : (h("div", { class: "mrd-table__filter-range" }, h("input", { type: inputType, class: "mrd-table__filter-input", placeholder: t('filter_from', this.locale), value: pf.from != null ? String(pf.from) : '', onInput: (e) => this.setPending('from', e.target.value) }), h("input", { type: inputType, class: "mrd-table__filter-input", placeholder: t('filter_to', this.locale), value: pf.to != null ? String(pf.to) : '', onInput: (e) => this.setPending('to', e.target.value) })))));
|
|
415
512
|
}
|
|
416
513
|
return null;
|
|
417
514
|
}
|
|
@@ -464,6 +561,15 @@ export class MrdTable {
|
|
|
464
561
|
this.mrdDownload.emit({ href, fileName });
|
|
465
562
|
} }, 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))) : ''));
|
|
466
563
|
}
|
|
564
|
+
const TEXTBLOCK_MAX = 200;
|
|
565
|
+
if (dataType === 'TEXTBLOCK') {
|
|
566
|
+
const full = CellRenderer.render(col, row, this.locale);
|
|
567
|
+
if (full.length <= TEXTBLOCK_MAX) {
|
|
568
|
+
return h("td", { class: "mrd-table__cell" }, full);
|
|
569
|
+
}
|
|
570
|
+
const preview = full.slice(0, TEXTBLOCK_MAX) + '…';
|
|
571
|
+
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")));
|
|
572
|
+
}
|
|
467
573
|
const value = CellRenderer.render(col, row, this.locale);
|
|
468
574
|
return (h("td", { class: `mrd-table__cell${isNumeric ? ' mrd-table__cell--numeric' : ''}` }, value));
|
|
469
575
|
}
|
|
@@ -478,8 +584,13 @@ export class MrdTable {
|
|
|
478
584
|
var _a, _b, _c, _d;
|
|
479
585
|
const name = this.colName(col);
|
|
480
586
|
const isFiltered = this.activeFilters.has(name);
|
|
481
|
-
|
|
482
|
-
|
|
587
|
+
const cls = [
|
|
588
|
+
'mrd-table__header',
|
|
589
|
+
isFiltered ? 'mrd-table__header--filtered' : '',
|
|
590
|
+
this.filterMode ? 'mrd-table__header--sortable' : '',
|
|
591
|
+
].filter(Boolean).join(' ');
|
|
592
|
+
return (h("th", { class: cls, onClick: this.filterMode ? (e) => this.handleFilterOpen(col, e) : undefined }, h("span", { class: "mrd-table__header-label" }, (_d = (_b = (_a = col.field) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : (_c = col.relation) === null || _c === void 0 ? void 0 : _c.label) !== null && _d !== void 0 ? _d : ''), isFiltered && this.renderFilterIcon()));
|
|
593
|
+
}))), 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.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()));
|
|
483
594
|
}
|
|
484
595
|
// ── Paginated / virtual-scroll mode ────────────────────────────────────
|
|
485
596
|
// Derive the authoritative row count from loaded pages:
|
|
@@ -521,8 +632,16 @@ export class MrdTable {
|
|
|
521
632
|
isActive ? `mrd-table__header--sorted-${this.sortDir}` : '',
|
|
522
633
|
isFiltered ? 'mrd-table__header--filtered' : '',
|
|
523
634
|
].filter(Boolean).join(' ');
|
|
524
|
-
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" },
|
|
525
|
-
}))), 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()));
|
|
635
|
+
return (h("th", { class: cls, style: this.colWidths[idx] ? { width: `${this.colWidths[idx]}px` } : undefined, onClick: (e) => this.filterMode ? this.handleFilterOpen(col, e) : 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 : ''), isActive && (h("span", { class: "mrd-table__sort-icon", "aria-hidden": "true" }, this.sortDir === 'asc' ? '▲' : '▼')), !isActive && !this.filterMode && (h("span", { class: "mrd-table__sort-icon", "aria-hidden": "true" }, "\u21C5")), isFiltered && this.renderFilterIcon()));
|
|
636
|
+
}))), 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(), this.renderTextblockModal()));
|
|
637
|
+
}
|
|
638
|
+
renderFilterIcon() {
|
|
639
|
+
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" }))));
|
|
640
|
+
}
|
|
641
|
+
renderTextblockModal() {
|
|
642
|
+
if (this.textblockModal === null)
|
|
643
|
+
return null;
|
|
644
|
+
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))));
|
|
526
645
|
}
|
|
527
646
|
static get is() { return "mrd-table"; }
|
|
528
647
|
static get encapsulation() { return "scoped"; }
|
|
@@ -747,7 +866,8 @@ export class MrdTable {
|
|
|
747
866
|
"openFilterCol": {},
|
|
748
867
|
"pendingFilter": {},
|
|
749
868
|
"popupPos": {},
|
|
750
|
-
"scrollTop": {}
|
|
869
|
+
"scrollTop": {},
|
|
870
|
+
"textblockModal": {}
|
|
751
871
|
};
|
|
752
872
|
}
|
|
753
873
|
static get events() {
|
|
@@ -73,7 +73,7 @@
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
.mrd-table__sort-icon {
|
|
76
|
-
font-size: 0.
|
|
76
|
+
font-size: 0.85rem;
|
|
77
77
|
opacity: 0.4;
|
|
78
78
|
vertical-align: middle;
|
|
79
79
|
}
|
|
@@ -84,6 +84,14 @@
|
|
|
84
84
|
color: var(--mrd-color-primary);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
.mrd-table__filter-icon {
|
|
88
|
+
display: inline-flex;
|
|
89
|
+
align-items: center;
|
|
90
|
+
vertical-align: middle;
|
|
91
|
+
margin-left: var(--mrd-space-1);
|
|
92
|
+
color: var(--mrd-color-primary);
|
|
93
|
+
}
|
|
94
|
+
|
|
87
95
|
/* ── Data rows ─────────────────────────────────────────────────────────── */
|
|
88
96
|
/* Background is set via inline style based on absolute row index,
|
|
89
97
|
so zebra striping stays correct even with virtual spacer rows. */
|
|
@@ -273,37 +281,12 @@
|
|
|
273
281
|
pointer-events: none;
|
|
274
282
|
}
|
|
275
283
|
|
|
276
|
-
/* ── Header: filtered indicator
|
|
284
|
+
/* ── Header: filtered indicator ─────────────────────────────────────────── */
|
|
277
285
|
.mrd-table__header--filtered {
|
|
278
286
|
color: var(--mrd-color-primary);
|
|
279
287
|
border-bottom-color: var(--mrd-color-primary);
|
|
280
288
|
}
|
|
281
289
|
|
|
282
|
-
.mrd-table__header-filter-btn {
|
|
283
|
-
display: inline-flex;
|
|
284
|
-
align-items: center;
|
|
285
|
-
justify-content: center;
|
|
286
|
-
margin-left: var(--mrd-space-1);
|
|
287
|
-
padding: 0 3px;
|
|
288
|
-
background: transparent;
|
|
289
|
-
border: none;
|
|
290
|
-
border-radius: 3px;
|
|
291
|
-
cursor: pointer;
|
|
292
|
-
color: var(--mrd-color-neutral-500);
|
|
293
|
-
font-size: 0.8rem;
|
|
294
|
-
line-height: 1;
|
|
295
|
-
vertical-align: middle;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
.mrd-table__header-filter-btn:hover {
|
|
299
|
-
background: var(--mrd-color-neutral-200);
|
|
300
|
-
color: var(--mrd-color-neutral-800);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
.mrd-table__header-filter-btn--active {
|
|
304
|
-
color: var(--mrd-color-primary);
|
|
305
|
-
}
|
|
306
|
-
|
|
307
290
|
/* ── Filter popup ───────────────────────────────────────────────────────── */
|
|
308
291
|
.mrd-table__filter-popup {
|
|
309
292
|
position: fixed;
|
|
@@ -433,6 +416,18 @@
|
|
|
433
416
|
flex-shrink: 0;
|
|
434
417
|
}
|
|
435
418
|
|
|
419
|
+
.mrd-table__filter-range--stacked {
|
|
420
|
+
flex-direction: column;
|
|
421
|
+
align-items: stretch;
|
|
422
|
+
gap: var(--mrd-space-2);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
.mrd-table__filter-range-label {
|
|
426
|
+
font-size: var(--mrd-font-size-xs);
|
|
427
|
+
color: var(--mrd-color-neutral-500);
|
|
428
|
+
margin-bottom: 2px;
|
|
429
|
+
}
|
|
430
|
+
|
|
436
431
|
/* Radio group */
|
|
437
432
|
.mrd-table__filter-radio-group {
|
|
438
433
|
display: flex;
|
|
@@ -576,3 +571,69 @@
|
|
|
576
571
|
height: 1rem;
|
|
577
572
|
}
|
|
578
573
|
|
|
574
|
+
/* ── TEXTBLOCK expand button ────────────────────────────────────────────── */
|
|
575
|
+
.mrd-table__textblock-btn {
|
|
576
|
+
display: inline;
|
|
577
|
+
background: none;
|
|
578
|
+
border: none;
|
|
579
|
+
padding: 0 0 0 var(--mrd-space-1);
|
|
580
|
+
cursor: pointer;
|
|
581
|
+
color: var(--mrd-color-primary);
|
|
582
|
+
font-size: var(--mrd-font-size-sm);
|
|
583
|
+
font-family: inherit;
|
|
584
|
+
line-height: inherit;
|
|
585
|
+
vertical-align: middle;
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
.mrd-table__textblock-btn:hover {
|
|
589
|
+
color: var(--mrd-color-primary-dark);
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
/* ── TEXTBLOCK modal ────────────────────────────────────────────────────── */
|
|
593
|
+
.mrd-table__modal-backdrop {
|
|
594
|
+
position: fixed;
|
|
595
|
+
inset: 0;
|
|
596
|
+
background: rgba(0, 0, 0, 0.4);
|
|
597
|
+
z-index: var(--mrd-z-modal, 300);
|
|
598
|
+
display: flex;
|
|
599
|
+
align-items: center;
|
|
600
|
+
justify-content: center;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
.mrd-table__modal {
|
|
604
|
+
background: #fff;
|
|
605
|
+
border-radius: var(--mrd-radius-md, 0.5rem);
|
|
606
|
+
padding: var(--mrd-space-6);
|
|
607
|
+
max-width: min(600px, 90vw);
|
|
608
|
+
max-height: 70vh;
|
|
609
|
+
overflow-y: auto;
|
|
610
|
+
position: relative;
|
|
611
|
+
box-shadow: var(--mrd-shadow-lg);
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
.mrd-table__modal-close {
|
|
615
|
+
position: absolute;
|
|
616
|
+
top: var(--mrd-space-3);
|
|
617
|
+
right: var(--mrd-space-3);
|
|
618
|
+
background: none;
|
|
619
|
+
border: none;
|
|
620
|
+
cursor: pointer;
|
|
621
|
+
font-size: 1.25rem;
|
|
622
|
+
line-height: 1;
|
|
623
|
+
color: var(--mrd-color-text-muted, #6b7280);
|
|
624
|
+
padding: 0;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
.mrd-table__modal-close:hover {
|
|
628
|
+
color: var(--mrd-color-text, #111827);
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
.mrd-table__modal-text {
|
|
632
|
+
margin: 0;
|
|
633
|
+
padding-right: var(--mrd-space-6);
|
|
634
|
+
white-space: pre-wrap;
|
|
635
|
+
word-break: break-word;
|
|
636
|
+
font-size: var(--mrd-font-size-sm);
|
|
637
|
+
line-height: 1.6;
|
|
638
|
+
}
|
|
639
|
+
|
|
@@ -431,14 +431,16 @@ function renderForm(layout, record = null, selfHref = null) {
|
|
|
431
431
|
|
|
432
432
|
form.addEventListener('mrdSearch', async (e) => {
|
|
433
433
|
logEvent('mrdSearch (live)', e.detail);
|
|
434
|
-
const { query, relatedClass } = e.detail;
|
|
435
|
-
|
|
436
|
-
if (!meta || !query || query.length < 2) return;
|
|
434
|
+
const { name, query, relatedClass } = e.detail;
|
|
435
|
+
if (!query || query.length < 2) return;
|
|
437
436
|
|
|
437
|
+
// relatedClass here is actually mostSignificantClass (the URL segment).
|
|
438
|
+
// Use name to find the exact field, avoiding collisions when multiple
|
|
439
|
+
// fields share the same mostSignificantClass (e.g. 'companies').
|
|
438
440
|
try {
|
|
439
|
-
const results = await apiSearchRelation(authGetToken(), _selectedTenant,
|
|
440
|
-
const host = Array.from(
|
|
441
|
-
.find(el => el.name ===
|
|
441
|
+
const results = await apiSearchRelation(authGetToken(), _selectedTenant, relatedClass, query);
|
|
442
|
+
const host = Array.from(form.querySelectorAll('mrd-relation-field'))
|
|
443
|
+
.find(el => el.name === name);
|
|
442
444
|
if (host && typeof host.setSearchResults === 'function') {
|
|
443
445
|
host.setSearchResults(results);
|
|
444
446
|
}
|
|
@@ -20,7 +20,7 @@ export function formatPercentage(value, locale, decimalPrecision = 2) {
|
|
|
20
20
|
style: 'percent',
|
|
21
21
|
minimumFractionDigits: decimalPrecision,
|
|
22
22
|
maximumFractionDigits: decimalPrecision,
|
|
23
|
-
}).format(value
|
|
23
|
+
}).format(value);
|
|
24
24
|
}
|
|
25
25
|
export function formatDate(value, locale) {
|
|
26
26
|
if (!value)
|
|
@@ -53,6 +53,9 @@ const translations = {
|
|
|
53
53
|
filter_select_none: 'Geen',
|
|
54
54
|
filter_search_value: 'Zoekwaarde...',
|
|
55
55
|
filter_no_support: 'Geen filtering beschikbaar voor dit veldtype.',
|
|
56
|
+
// mrd-table textblock
|
|
57
|
+
textblock_show_more: 'Meer tonen',
|
|
58
|
+
close: 'Sluiten',
|
|
56
59
|
},
|
|
57
60
|
en: {
|
|
58
61
|
required: 'This field is required',
|
|
@@ -108,6 +111,9 @@ const translations = {
|
|
|
108
111
|
filter_select_none: 'None',
|
|
109
112
|
filter_search_value: 'Search value...',
|
|
110
113
|
filter_no_support: 'Filtering is not available for this field type.',
|
|
114
|
+
// mrd-table textblock
|
|
115
|
+
textblock_show_more: 'Show more',
|
|
116
|
+
close: 'Close',
|
|
111
117
|
},
|
|
112
118
|
ar: {
|
|
113
119
|
required: 'هذا الحقل مطلوب',
|
|
@@ -163,6 +169,9 @@ const translations = {
|
|
|
163
169
|
filter_select_none: 'لا شيء',
|
|
164
170
|
filter_search_value: 'قيمة البحث...',
|
|
165
171
|
filter_no_support: 'التصفية غير متاحة لهذا النوع من الحقول.',
|
|
172
|
+
// mrd-table textblock
|
|
173
|
+
textblock_show_more: 'عرض المزيد',
|
|
174
|
+
close: 'إغلاق',
|
|
166
175
|
},
|
|
167
176
|
fr: {
|
|
168
177
|
required: 'Ce champ est obligatoire',
|
|
@@ -218,6 +227,9 @@ const translations = {
|
|
|
218
227
|
filter_select_none: 'Aucun',
|
|
219
228
|
filter_search_value: 'Valeur de recherche...',
|
|
220
229
|
filter_no_support: "Le filtrage n'est pas disponible pour ce type de champ.",
|
|
230
|
+
// mrd-table textblock
|
|
231
|
+
textblock_show_more: 'Voir plus',
|
|
232
|
+
close: 'Fermer',
|
|
221
233
|
},
|
|
222
234
|
};
|
|
223
235
|
export function t(key, locale) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function n(n,i,t){return null==n||isNaN(n)?"":new Intl.NumberFormat(i,t).format(n)}function i(n,i,t){return null==n||isNaN(n)?"":new Intl.NumberFormat(t,{style:"currency",currency:i,minimumFractionDigits:2,maximumFractionDigits:2}).format(n)}function t(n,i,t=2){return null==n||isNaN(n)?"":new Intl.NumberFormat(i,{style:"percent",minimumFractionDigits:t,maximumFractionDigits:t}).format(n
|
|
1
|
+
function n(n,i,t){return null==n||isNaN(n)?"":new Intl.NumberFormat(i,t).format(n)}function i(n,i,t){return null==n||isNaN(n)?"":new Intl.NumberFormat(t,{style:"currency",currency:i,minimumFractionDigits:2,maximumFractionDigits:2}).format(n)}function t(n,i,t=2){return null==n||isNaN(n)?"":new Intl.NumberFormat(i,{style:"percent",minimumFractionDigits:t,maximumFractionDigits:t}).format(n)}function e(n,i){if(!n)return"";const t="string"==typeof n?new Date(n):n;return isNaN(t.getTime())?"":new Intl.DateTimeFormat(i,{year:"numeric",month:"2-digit",day:"2-digit"}).format(t)}function r(n,i){if(!n)return"";const t="string"==typeof n?new Date(n):n;return isNaN(t.getTime())?"":new Intl.DateTimeFormat(i,{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit"}).format(t)}function u(n,i){if(!n)return"";const[t,e]=n.split(":").map(Number),r=new Date;return r.setHours(t,e,0,0),new Intl.DateTimeFormat(i,{hour:"2-digit",minute:"2-digit"}).format(r)}function a(n,i){var t,e,r,u;if(!n||!n.trim())return null;const a=new Intl.NumberFormat(i).formatToParts(1234567.89),o=null!==(e=null===(t=a.find((n=>"group"===n.type)))||void 0===t?void 0:t.value)&&void 0!==e?e:",",l=null!==(u=null===(r=a.find((n=>"decimal"===n.type)))||void 0===r?void 0:r.value)&&void 0!==u?u:".",s=n.replace(new RegExp(`\\${o}`,"g"),"").replace(new RegExp(`\\${l}`),".").replace("%","").trim(),c=parseFloat(s);return isNaN(c)?null:c}export{u as a,r as b,e as c,i as d,t as e,n as f,a as p}
|