@mmlogic/components 0.5.4 → 0.5.5
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/{cell-renderer-Coy-aD3k.js → cell-renderer-Mx3pwONr.js} +237 -0
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/mosterdcomponents.cjs.js +1 -1
- package/dist/cjs/mrd-boolean-field_25.cjs.entry.js +296 -56
- package/dist/cjs/mrd-merge-view.cjs.entry.js +3 -3
- package/dist/collection/components/fields/mrd-currency-field/mrd-currency-field.js +56 -5
- package/dist/collection/components/fields/mrd-date-field/mrd-date-field.css +55 -4
- package/dist/collection/components/fields/mrd-date-field/mrd-date-field.js +118 -8
- package/dist/collection/components/fields/mrd-datetime-field/mrd-datetime-field.css +55 -4
- package/dist/collection/components/fields/mrd-datetime-field/mrd-datetime-field.js +117 -15
- package/dist/collection/components/fields/mrd-email-field/mrd-email-field.js +1 -1
- package/dist/collection/components/fields/mrd-file-field/mrd-file-field.js +1 -1
- package/dist/collection/components/fields/mrd-image-field/mrd-image-field.js +1 -1
- package/dist/collection/components/fields/mrd-longtext-field/mrd-longtext-field.js +1 -1
- package/dist/collection/components/fields/mrd-number-field/mrd-number-field.js +33 -8
- package/dist/collection/components/fields/mrd-secret-field/mrd-secret-field.js +2 -2
- package/dist/collection/components/fields/mrd-text-field/mrd-text-field.js +1 -1
- package/dist/collection/components/fields/mrd-textarea-field/mrd-textarea-field.js +1 -1
- package/dist/collection/components/fields/mrd-time-field/mrd-time-field.js +1 -1
- package/dist/collection/components/form/mrd-field/mrd-field.js +11 -11
- package/dist/collection/components/invoice/mrd-invoice-view/mrd-invoice-view.js +1 -1
- package/dist/collection/components/layout/mrd-layout-section/mrd-layout-section.js +1 -1
- package/dist/collection/components/merge/mrd-merge-view/mrd-merge-view.js +2 -2
- package/dist/collection/dev/app.js +58 -13
- package/dist/collection/utils/format.js +160 -0
- package/dist/collection/utils/i18n.js +72 -0
- package/dist/components/cell-renderer.js +1 -1
- package/dist/components/format.js +1 -1
- package/dist/components/i18n.js +1 -1
- package/dist/components/mrd-currency-field2.js +1 -1
- package/dist/components/mrd-date-field2.js +1 -1
- package/dist/components/mrd-datetime-field2.js +1 -1
- package/dist/components/mrd-document-list2.js +1 -1
- package/dist/components/mrd-document-view2.js +1 -1
- package/dist/components/mrd-email-field2.js +1 -1
- package/dist/components/mrd-email-view2.js +1 -1
- package/dist/components/mrd-field2.js +1 -1
- package/dist/components/mrd-file-field2.js +1 -1
- package/dist/components/mrd-image-field2.js +1 -1
- package/dist/components/mrd-invoice-view2.js +1 -1
- package/dist/components/mrd-layout-section.js +1 -1
- package/dist/components/mrd-longtext-field2.js +1 -1
- package/dist/components/mrd-merge-view.js +1 -1
- package/dist/components/mrd-number-field2.js +1 -1
- package/dist/components/mrd-secret-field2.js +1 -1
- package/dist/components/mrd-table2.js +1 -1
- package/dist/components/mrd-text-field2.js +1 -1
- package/dist/components/mrd-textarea-field2.js +1 -1
- package/dist/components/mrd-time-field2.js +1 -1
- package/dist/esm/{cell-renderer-C2FLUrMN.js → cell-renderer-UQOYlDv7.js} +233 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/mosterdcomponents.js +1 -1
- package/dist/esm/mrd-boolean-field_25.entry.js +296 -56
- package/dist/esm/mrd-merge-view.entry.js +3 -3
- package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
- package/dist/mosterdcomponents/p-8cc374e0.entry.js +3 -0
- package/dist/mosterdcomponents/p-CF--ScWr.js +1 -0
- package/dist/mosterdcomponents/{p-4ea5b97c.entry.js → p-d31b71d9.entry.js} +1 -1
- package/dist/types/components/fields/mrd-currency-field/mrd-currency-field.d.ts +13 -0
- package/dist/types/components/fields/mrd-date-field/mrd-date-field.d.ts +22 -1
- package/dist/types/components/fields/mrd-datetime-field/mrd-datetime-field.d.ts +21 -2
- package/dist/types/components/fields/mrd-number-field/mrd-number-field.d.ts +6 -0
- package/dist/types/components.d.ts +26 -0
- package/dist/types/utils/format.d.ts +34 -0
- package/package.json +1 -1
- package/dist/mosterdcomponents/p-8736313b.entry.js +0 -3
- package/dist/mosterdcomponents/p-BgsPVesg.js +0 -1
|
@@ -112,7 +112,7 @@ export class MrdFileField {
|
|
|
112
112
|
error: hasError,
|
|
113
113
|
disabled: this.disabled || this.zoneBusy,
|
|
114
114
|
});
|
|
115
|
-
return (h(Host, { key: '
|
|
115
|
+
return (h(Host, { key: '36f9660fd297e7b2e7b2ac1816f4dcbc70d5cfcb' }, h("div", { key: 'a33534d3fedae04bad0eefc9d2d297ea148c5784', class: "mrd-file-field" }, h(FieldLabel, { key: '833f8ff178ec259c8066ddf542bdd1930bac486f', base: "mrd-file-field", label: this.label, required: this.required }), h("div", { key: 'd3bd00b25329b8cc716c5fcc526919d8f2c14bce', class: zoneClass, onClick: this.handleZoneClick, onDragOver: this.drag.onDragOver, onDragLeave: this.drag.onDragLeave, onDrop: this.drag.onDrop }, h("input", { key: '4b98ee338e8a5e4e6f94e5b5614ca88c90f802ee', ref: el => (this.fileInputRef = el), class: "mrd-file-field__input", type: "file", name: this.name, accept: this.accept, multiple: this.multiple, disabled: this.disabled || this.zoneBusy, required: this.required && !hasEntries, onChange: this.handleInputChange }), hasEntries && !this.multiple ? (h("div", { class: "mrd-file-field__selected" }, this.renderEntry(this.entries[0], 0))) : (h("div", { class: "mrd-file-field__prompt" }, h("svg", { class: "mrd-file-field__upload-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2" }, h("polyline", { points: "16 16 12 12 8 16" }), h("line", { x1: "12", y1: "12", x2: "12", y2: "21" }), h("path", { d: "M20.39 18.39A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.3" })), h("span", null, t('drop_file_here', this.locale), ' ', h("span", { class: "mrd-file-field__browse" }, t('browse', this.locale)))))), this.multiple && hasEntries && (h("ul", { key: '6e6e1d62738d0a824eb86e0dbb01b63a0227580d', class: "mrd-file-field__list" }, this.entries.map((entry, index) => (h("li", { class: "mrd-file-field__item", key: `${index}-${entryLabel(entry)}` }, this.renderEntry(entry, index)))))), h(FieldError, { key: 'df6427015d3f813a72e8998f9fa6152f6caef90e', base: "mrd-file-field", error: this.error }))));
|
|
116
116
|
}
|
|
117
117
|
static get is() { return "mrd-file-field"; }
|
|
118
118
|
static get encapsulation() { return "scoped"; }
|
|
@@ -130,7 +130,7 @@ export class MrdImageField {
|
|
|
130
130
|
error: hasError,
|
|
131
131
|
disabled: this.disabled || this.zoneBusy,
|
|
132
132
|
});
|
|
133
|
-
return (h(Host, { key: '
|
|
133
|
+
return (h(Host, { key: '5009b2db845c8f85f395c7230e2d5c464c56ea14' }, h("div", { key: 'fcae7821876ee3d71aac576cdea44c3c4f169890', class: "mrd-image-field" }, h(FieldLabel, { key: '834638e3f7b2073508d98b6dd5ecb437b0bb52ad', base: "mrd-image-field", label: this.label, required: this.required }), h("div", { key: '50e9bdaa1ebb3ec87f36e0d37dc6c2f8dc79848d', class: zoneClass, onClick: this.handleZoneClick, onDragOver: this.drag.onDragOver, onDragLeave: this.drag.onDragLeave, onDrop: this.drag.onDrop }, h("input", { key: '38e115fae5b3e2c3371857d284fbd54ea23812df', ref: el => (this.fileInputRef = el), class: "mrd-image-field__input", type: "file", name: this.name, accept: this.accept, multiple: this.multiple, disabled: this.disabled || this.zoneBusy, required: this.required && !hasEntries, onChange: this.handleInputChange }), hasEntries && !this.multiple ? (this.renderSingle(this.entries[0])) : (h("div", { class: "mrd-image-field__prompt" }, h("svg", { class: "mrd-image-field__upload-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2" }, h("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }), h("circle", { cx: "8.5", cy: "8.5", r: "1.5" }), h("polyline", { points: "21 15 16 10 5 21" })), h("span", null, t('drop_file_here', this.locale), ' ', h("span", { class: "mrd-image-field__browse" }, t('browse', this.locale)))))), this.multiple && hasEntries && (h("ul", { key: '67bad2f2142f78d7f25b8f35819b6adba48ea597', class: "mrd-image-field__grid" }, this.entries.map((entry, index) => this.renderGridItem(entry, index)))), h(FieldError, { key: 'ef07863946f0b4c94aa30b97d0ecb9616303e793', base: "mrd-image-field", error: this.error }))));
|
|
134
134
|
}
|
|
135
135
|
static get is() { return "mrd-image-field"; }
|
|
136
136
|
static get encapsulation() { return "scoped"; }
|
|
@@ -21,7 +21,7 @@ export class MrdLongtextField {
|
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
render() {
|
|
24
|
-
return (h(Host, { key: '
|
|
24
|
+
return (h(Host, { key: 'a43ce67cb05e96853193e56c175d99e51d07cbab' }, h("div", { key: 'eb7d09bcae010736dd17b5f17bcb1cb32a6b1c4e', class: "mrd-longtext-field" }, h(FieldLabel, { key: 'd3a47993cc977c06b845eda4575b93d238eaf15a', base: "mrd-longtext-field", label: this.label, required: this.required }), this.disabled ? (h("pre", { class: "mrd-longtext-field__content" }, this.value)) : (h("textarea", { class: controlClass('mrd-longtext-field', !!this.error), name: this.name, placeholder: this.placeholder, required: this.required, rows: 10, onInput: this.handleInput, onBlur: this.handleBlur }, this.value)), h(FieldError, { key: '89f801af61fc0b874db44dbfca6eb33ffe285a84', base: "mrd-longtext-field", error: this.error }))));
|
|
25
25
|
}
|
|
26
26
|
static get is() { return "mrd-longtext-field"; }
|
|
27
27
|
static get encapsulation() { return "scoped"; }
|
|
@@ -17,10 +17,13 @@ export class MrdNumberField {
|
|
|
17
17
|
this.decimalPrecision = 2;
|
|
18
18
|
this.displayValue = '';
|
|
19
19
|
this.error = '';
|
|
20
|
+
/** While focused the user owns the text; prop updates must not overwrite it. */
|
|
21
|
+
this.focused = false;
|
|
20
22
|
this.handleInput = (e) => {
|
|
21
23
|
this.displayValue = e.target.value;
|
|
22
24
|
};
|
|
23
25
|
this.handleBlur = (e) => {
|
|
26
|
+
this.focused = false;
|
|
24
27
|
const raw = e.target.value;
|
|
25
28
|
const parsed = parseLocalizedNumber(raw, this.locale);
|
|
26
29
|
if (this.required && (parsed === null || raw === '')) {
|
|
@@ -39,17 +42,30 @@ export class MrdNumberField {
|
|
|
39
42
|
this.mrdBlur.emit({ name: this.name, value: parsed });
|
|
40
43
|
};
|
|
41
44
|
this.handleFocus = () => {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
this.focused = true;
|
|
46
|
+
// Drop the grouping separators while editing, but keep the locale's decimal
|
|
47
|
+
// separator: String(1234.56) would be re-read as 123456 where '.' groups.
|
|
48
|
+
const parsed = parseLocalizedNumber(this.displayValue, this.locale);
|
|
49
|
+
if (parsed !== null) {
|
|
50
|
+
this.displayValue = formatNumber(parsed, this.locale, { useGrouping: false, maximumFractionDigits: 20 });
|
|
46
51
|
}
|
|
47
52
|
};
|
|
48
53
|
}
|
|
49
54
|
componentWillLoad() {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
55
|
+
this.syncFromValue();
|
|
56
|
+
}
|
|
57
|
+
/** Edit mode loads the record after mount, so the incoming value must re-sync. */
|
|
58
|
+
valueChanged() {
|
|
59
|
+
if (!this.focused)
|
|
60
|
+
this.syncFromValue();
|
|
61
|
+
}
|
|
62
|
+
localeChanged() {
|
|
63
|
+
if (!this.focused)
|
|
64
|
+
this.syncFromValue();
|
|
65
|
+
}
|
|
66
|
+
syncFromValue() {
|
|
67
|
+
this.displayValue =
|
|
68
|
+
this.value !== null && this.value !== undefined ? this.formatForDisplay(this.value) : '';
|
|
53
69
|
}
|
|
54
70
|
formatForDisplay(val) {
|
|
55
71
|
if (this.dataType === ClientLayoutItemFieldDataType.PERCENTAGE) {
|
|
@@ -70,7 +86,7 @@ export class MrdNumberField {
|
|
|
70
86
|
const hasError = !!this.error;
|
|
71
87
|
const suffix = this.dataType === ClientLayoutItemFieldDataType.PERCENTAGE ? '%' :
|
|
72
88
|
this.dataType === ClientLayoutItemFieldDataType.DECIMAL ? '' : '';
|
|
73
|
-
return (h(Host, { key: '
|
|
89
|
+
return (h(Host, { key: 'bd5eb25cf7b97ef2ddb67a6bc6d6d96c9bff7510' }, h("div", { key: '68b15887a045f743a7f177e7a178146a9f4e0400', class: "mrd-number-field" }, h(FieldLabel, { key: '72e88a34a390e36ee11f5840d87dedd9d4d7fb12', base: "mrd-number-field", label: this.label, required: this.required }), h("div", { key: 'd97dae69eedf4c0ed1c872065754327dbffb5ba7', class: "mrd-number-field__input-wrapper" }, h("input", { key: '5767f6c34a08f503a1a157390c679382c857ff01', class: controlClass('mrd-number-field', hasError), type: "text", inputMode: "decimal", name: this.name, value: this.displayValue, placeholder: this.placeholder || (suffix ? `0${suffix}` : '0'), required: this.required, disabled: this.disabled, onInput: this.handleInput, onBlur: this.handleBlur, onFocus: this.handleFocus })), h(FieldError, { key: '1d4f8ffd3fcdf2ae2e8eb1eb68c051619d66c954', base: "mrd-number-field", error: this.error }))));
|
|
74
90
|
}
|
|
75
91
|
static get is() { return "mrd-number-field"; }
|
|
76
92
|
static get encapsulation() { return "scoped"; }
|
|
@@ -314,4 +330,13 @@ export class MrdNumberField {
|
|
|
314
330
|
}
|
|
315
331
|
}];
|
|
316
332
|
}
|
|
333
|
+
static get watchers() {
|
|
334
|
+
return [{
|
|
335
|
+
"propName": "value",
|
|
336
|
+
"methodName": "valueChanged"
|
|
337
|
+
}, {
|
|
338
|
+
"propName": "locale",
|
|
339
|
+
"methodName": "localeChanged"
|
|
340
|
+
}];
|
|
341
|
+
}
|
|
317
342
|
}
|
|
@@ -21,9 +21,9 @@ export class MrdSecretField {
|
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
render() {
|
|
24
|
-
return (h(Host, { key: '
|
|
24
|
+
return (h(Host, { key: 'd3d204242898c1f258b088e7b5428421cde8d7a7' }, h("div", { key: '11d284625cdd1e0def58cc31eab9bbe59346649d', class: "mrd-secret-field" }, h(FieldLabel, { key: '333e5b23d2379125a393f555b936be7bc521fdb4', base: "mrd-secret-field", label: this.label, required: this.required }), this.disabled
|
|
25
25
|
? (h("span", { class: "mrd-secret-field__masked", "aria-label": this.label }, this.value ? '••••••••' : ''))
|
|
26
|
-
: (h("input", { class: controlClass('mrd-secret-field', !!this.error), type: "password", name: this.name, value: this.value, placeholder: this.placeholder, required: this.required, autocomplete: "new-password", onInput: this.handleInput, onBlur: this.handleBlur })), h(FieldError, { key: '
|
|
26
|
+
: (h("input", { class: controlClass('mrd-secret-field', !!this.error), type: "password", name: this.name, value: this.value, placeholder: this.placeholder, required: this.required, autocomplete: "new-password", onInput: this.handleInput, onBlur: this.handleBlur })), h(FieldError, { key: 'cc202197fdab62da7b5083e078e69efd86e673ca', base: "mrd-secret-field", error: this.error }))));
|
|
27
27
|
}
|
|
28
28
|
static get is() { return "mrd-secret-field"; }
|
|
29
29
|
static get encapsulation() { return "scoped"; }
|
|
@@ -21,7 +21,7 @@ export class MrdTextField {
|
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
render() {
|
|
24
|
-
return (h(Host, { key: '
|
|
24
|
+
return (h(Host, { key: '145aa80d06459fe85650702ced893e102762afa8' }, h("div", { key: '8f08af9acff56e704d216dc185a5d344b5b9f671', class: "mrd-text-field" }, h(FieldLabel, { key: '4e0204ffe7e8460eaf9a4be1535252cc11d0bab7', base: "mrd-text-field", label: this.label, required: this.required }), h("input", { key: '4d519077ad96c121ede51e188a2151efe72811db', class: controlClass('mrd-text-field', !!this.error), type: "text", name: this.name, value: this.value, placeholder: this.placeholder, required: this.required, disabled: this.disabled, onInput: this.handleInput, onBlur: this.handleBlur }), h(FieldError, { key: '3c5af47037f6d6851503d769429d6c0f786d389d', base: "mrd-text-field", error: this.error }))));
|
|
25
25
|
}
|
|
26
26
|
static get is() { return "mrd-text-field"; }
|
|
27
27
|
static get encapsulation() { return "scoped"; }
|
|
@@ -64,7 +64,7 @@ export class MrdTextareaField {
|
|
|
64
64
|
return DOMPurify.sanitize(html);
|
|
65
65
|
}
|
|
66
66
|
render() {
|
|
67
|
-
return (h(Host, { key: '
|
|
67
|
+
return (h(Host, { key: 'e7c53e9cf54bd4138b42ca3bc7bb5381aad3e4ac' }, h("div", { key: 'bf580a74d2233704852c7d3083ec91c9bbe868ad', class: "mrd-textarea-field" }, h(FieldLabel, { key: '7de50cb2865e83c7fe1ef9b6b099b639e165909c', base: "mrd-textarea-field", label: this.label, required: this.required }), h("div", { key: 'c78e914091cd70b52c1e9cd0046e7c97bcc7e799', class: controlClass('mrd-textarea-field', !!this.error, 'container') }, h("div", { key: '604a157e82ca8a4d98bbd1c928e9f8b41d031227', class: "mrd-textarea-field__editor" })), h(FieldError, { key: 'd0263a7285b928be6ed377e7e0fa3f53a555dadd', base: "mrd-textarea-field", error: this.error }))));
|
|
68
68
|
}
|
|
69
69
|
static get is() { return "mrd-textarea-field"; }
|
|
70
70
|
static get encapsulation() { return "scoped"; }
|
|
@@ -20,7 +20,7 @@ export class MrdTimeField {
|
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
render() {
|
|
23
|
-
return (h(Host, { key: '
|
|
23
|
+
return (h(Host, { key: 'ef3876dd5c1d72bdbdb65cba00ea0992ba2ab2b6' }, h("div", { key: '6b217f6c6ec0dbb8b3249dfab6443b8f6140891c', class: "mrd-time-field" }, h(FieldLabel, { key: '87adbcc4bf1ccad07d899a315cb14a00650af09c', base: "mrd-time-field", label: this.label, required: this.required }), h("input", { key: '870fcf7e0df2ee2804f95fdc79c890b3e27bba3f', class: controlClass('mrd-time-field', !!this.error), type: "time", name: this.name, value: this.value, required: this.required, disabled: this.disabled, onChange: this.handleChange, onBlur: this.handleBlur }), h(FieldError, { key: '03c21d23fbc039ffd79856134d181dffcb9e3621', base: "mrd-time-field", error: this.error }))));
|
|
24
24
|
}
|
|
25
25
|
static get is() { return "mrd-time-field"; }
|
|
26
26
|
static get encapsulation() { return "scoped"; }
|
|
@@ -111,7 +111,7 @@ export class MrdField {
|
|
|
111
111
|
return (h("div", { class: "mrd-field__history-editor" }, this.historyEntries.length > 0 && (h("span", { class: "mrd-field__history-editor-label" }, t('history_badge_tooltip', locale))), this.historyEntries.map((entry, i) => (h("div", { key: String(i), class: "mrd-field__history-editor-row" }, h("input", { class: "mrd-field__history-editor-value", type: valueType, value: entry.value, onInput: (e) => updateEntry(i, 'value', e.target.value) }), h("span", { class: "mrd-field__history-editor-sep" }, t('history_until', locale)), h("input", { class: "mrd-field__history-editor-until", type: "date", value: entry.until, onInput: (e) => updateEntry(i, 'until', e.target.value) }), h("button", { type: "button", class: "mrd-field__history-editor-remove", onClick: () => removeEntry(i), "aria-label": t('remove', locale) }, h("svg", { viewBox: "0 0 20 20", fill: "currentColor", "aria-hidden": "true" }, h("path", { "fill-rule": "evenodd", d: "M8.75 1A2.75 2.75 0 006 3.75v.443c-.795.077-1.584.176-2.365.298a.75.75 0 10.23 1.482l.149-.022.841 10.518A2.75 2.75 0 007.596 19h4.807a2.75 2.75 0 002.742-2.53l.841-10.52.149.023a.75.75 0 00.23-1.482A41.03 41.03 0 0014 4.193V3.75A2.75 2.75 0 0011.25 1h-2.5zM10 4c.84 0 1.673.025 2.5.075V3.75c0-.69-.56-1.25-1.25-1.25h-2.5c-.69 0-1.25.56-1.25 1.25v.325C8.327 4.025 9.16 4 10 4zM8.58 7.72a.75.75 0 00-1.5.06l.3 7.5a.75.75 0 101.5-.06l-.3-7.5zm4.34.06a.75.75 0 10-1.5-.06l-.3 7.5a.75.75 0 101.5.06l.3-7.5z", "clip-rule": "evenodd" })))))), h("button", { type: "button", class: "mrd-field__history-editor-add", onClick: addEntry }, "+ ", t('add', locale))));
|
|
112
112
|
}
|
|
113
113
|
renderLeafField(displayValue) {
|
|
114
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6;
|
|
114
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8;
|
|
115
115
|
const { item, locale } = this;
|
|
116
116
|
const commonProps = {
|
|
117
117
|
name: item.name,
|
|
@@ -136,25 +136,25 @@ export class MrdField {
|
|
|
136
136
|
case ClientLayoutItemFieldDataType.BOOLEAN:
|
|
137
137
|
return (h("mrd-boolean-field", Object.assign({}, commonProps, { value: (_l = displayValue) !== null && _l !== void 0 ? _l : false })));
|
|
138
138
|
case ClientLayoutItemFieldDataType.DATE:
|
|
139
|
-
return (h("mrd-date-field", Object.assign({}, commonProps, { value: (_m = displayValue) !== null && _m !== void 0 ? _m : '' })));
|
|
139
|
+
return (h("mrd-date-field", Object.assign({}, commonProps, { value: (_m = displayValue) !== null && _m !== void 0 ? _m : '', placeholder: (_o = item.placeholder) !== null && _o !== void 0 ? _o : '' })));
|
|
140
140
|
case ClientLayoutItemFieldDataType.DATETIME:
|
|
141
|
-
return (h("mrd-datetime-field", Object.assign({}, commonProps, { value: (
|
|
141
|
+
return (h("mrd-datetime-field", Object.assign({}, commonProps, { value: (_p = displayValue) !== null && _p !== void 0 ? _p : '', placeholder: (_q = item.placeholder) !== null && _q !== void 0 ? _q : '' })));
|
|
142
142
|
case ClientLayoutItemFieldDataType.TIME:
|
|
143
|
-
return (h("mrd-time-field", Object.assign({}, commonProps, { value: (
|
|
143
|
+
return (h("mrd-time-field", Object.assign({}, commonProps, { value: (_r = displayValue) !== null && _r !== void 0 ? _r : '' })));
|
|
144
144
|
case ClientLayoutItemFieldDataType.EMAIL:
|
|
145
|
-
return (h("mrd-email-field", Object.assign({}, commonProps, { value: (
|
|
145
|
+
return (h("mrd-email-field", Object.assign({}, commonProps, { value: (_s = displayValue) !== null && _s !== void 0 ? _s : '', placeholder: (_t = item.placeholder) !== null && _t !== void 0 ? _t : '' })));
|
|
146
146
|
case ClientLayoutItemFieldDataType.HYPERLINK:
|
|
147
|
-
return (h("mrd-hyperlink-field", Object.assign({}, commonProps, { value: (
|
|
147
|
+
return (h("mrd-hyperlink-field", Object.assign({}, commonProps, { value: (_u = displayValue) !== null && _u !== void 0 ? _u : '', placeholder: (_v = item.placeholder) !== null && _v !== void 0 ? _v : '' })));
|
|
148
148
|
case ClientLayoutItemFieldDataType.LIST:
|
|
149
|
-
return (h("mrd-list-field", Object.assign({}, commonProps, { value: (
|
|
149
|
+
return (h("mrd-list-field", Object.assign({}, commonProps, { value: (_w = displayValue) !== null && _w !== void 0 ? _w : '', multiple: (_x = item.multiple) !== null && _x !== void 0 ? _x : false, listItems: (_y = item.listItems) !== null && _y !== void 0 ? _y : [] })));
|
|
150
150
|
case ClientLayoutItemFieldDataType.FILE:
|
|
151
|
-
return (h("mrd-file-field", Object.assign({}, commonProps, { value: displayValue, accept: (
|
|
151
|
+
return (h("mrd-file-field", Object.assign({}, commonProps, { value: displayValue, accept: (_z = item.accept) !== null && _z !== void 0 ? _z : '', maxSize: (_0 = item.maxSize) !== null && _0 !== void 0 ? _0 : 0, multiple: (_1 = item.multiple) !== null && _1 !== void 0 ? _1 : false, onMrdUpload: this.handleUpload })));
|
|
152
152
|
case ClientLayoutItemFieldDataType.IMAGE:
|
|
153
|
-
return (h("mrd-image-field", Object.assign({}, commonProps, { value: displayValue, accept: (
|
|
153
|
+
return (h("mrd-image-field", Object.assign({}, commonProps, { value: displayValue, accept: (_2 = item.accept) !== null && _2 !== void 0 ? _2 : 'image/*', maxSize: (_3 = item.maxSize) !== null && _3 !== void 0 ? _3 : 0, multiple: (_4 = item.multiple) !== null && _4 !== void 0 ? _4 : false, onMrdUpload: this.handleUpload })));
|
|
154
154
|
case ClientLayoutItemFieldDataType.LONGTEXT:
|
|
155
|
-
return (h("mrd-longtext-field", Object.assign({}, commonProps, { value: (
|
|
155
|
+
return (h("mrd-longtext-field", Object.assign({}, commonProps, { value: (_5 = displayValue) !== null && _5 !== void 0 ? _5 : '', placeholder: (_6 = item.placeholder) !== null && _6 !== void 0 ? _6 : '' })));
|
|
156
156
|
case ClientLayoutItemFieldDataType.SECRET:
|
|
157
|
-
return (h("mrd-secret-field", Object.assign({}, commonProps, { value: (
|
|
157
|
+
return (h("mrd-secret-field", Object.assign({}, commonProps, { value: (_7 = displayValue) !== null && _7 !== void 0 ? _7 : '', placeholder: (_8 = item.placeholder) !== null && _8 !== void 0 ? _8 : '' })));
|
|
158
158
|
default:
|
|
159
159
|
return null;
|
|
160
160
|
}
|
|
@@ -107,7 +107,7 @@ export class MrdInvoiceView {
|
|
|
107
107
|
const invoiceDateRaw = this.slotValue('invoiceDate');
|
|
108
108
|
const dueDateRaw = this.slotValue('dueDate');
|
|
109
109
|
const hasLines = !!((_b = (_a = this.archetype) === null || _a === void 0 ? void 0 : _a.slots) === null || _b === void 0 ? void 0 : _b['lines']);
|
|
110
|
-
return (h(Host, { key: '
|
|
110
|
+
return (h(Host, { key: '8005640e6d13004ae2fdf5f48129214fbc8c55fc' }, h("div", { key: '992f925691e2455c8888df76f93176cec5866210', class: "mrd-invoice-view" }, h("div", { key: 'aa418658cfe830be4e0f8bf77af42a898c9170db', class: "mrd-invoice-view__header" }, h("div", { key: 'ce10fef2072c26a0eb8f7ead620cb460af6646f0', class: "mrd-invoice-view__title-row" }, invoiceNumber && h("h1", { key: '992486cd5dc0bfb9761bdc94bcd237e6bd6e3d24', class: "mrd-invoice-view__title" }, t('invoice_title', this.locale), " ", invoiceNumber), this.renderStatus()), h("div", { key: 'a8c5d2516b737d4dcd5d0f966aadcda4d47a63ad', class: "mrd-invoice-view__dates" }, invoiceDateRaw != null && invoiceDateRaw !== '' && (h("span", { key: 'dd728929fc408c280ad81e212bdfac5905cda02d' }, t('invoice_date', this.locale), ": ", formatDate(invoiceDateRaw, this.locale))), dueDateRaw != null && dueDateRaw !== '' && (h("span", { key: 'd4226d5cc37f0152950f44a3b63a88f0454919bd' }, t('invoice_due_date', this.locale), ": ", formatDate(dueDateRaw, this.locale)))), this.renderContainer()), h("div", { key: 'c40b00c852d005963be7b5006e13804e72ba032a', class: "mrd-invoice-view__parties" }, this.renderPartyLink('customer', t('invoice_customer', this.locale)), this.renderPartyLink('supplier', t('invoice_supplier', this.locale))), hasLines && (h("div", { key: '000e991c64daa582194631b2eac6b1acba418e97', class: "mrd-invoice-view__lines" }, h("slot", { key: '97ba2acb750137eeb5ed6b5e9e5d277f638d4f0a', name: "lines" }))), this.renderAmounts(), this.renderAttachments())));
|
|
111
111
|
}
|
|
112
112
|
static get is() { return "mrd-invoice-view"; }
|
|
113
113
|
static get encapsulation() { return "scoped"; }
|
|
@@ -359,7 +359,7 @@ export class MrdLayoutSection {
|
|
|
359
359
|
const docArchetype = resolveArchetype(this.archetypes, ARCHETYPE_DOCUMENT);
|
|
360
360
|
const invoiceArchetype = !docArchetype ? resolveArchetype(this.archetypes, ARCHETYPE_INVOICE) : undefined;
|
|
361
361
|
const emailArchetype = !docArchetype && !invoiceArchetype ? resolveArchetype(this.archetypes, ARCHETYPE_EMAIL) : undefined;
|
|
362
|
-
return (h(Host, { key: '
|
|
362
|
+
return (h(Host, { key: '8c4e0a0e71d777295010702584b4aa8f7817cafb' }, h("div", { key: 'fe021021eba48acad3d52ee4849ebe355e83c348', class: "mrd-layout-section" }, docArchetype && this.renderDocumentObject(docArchetype), invoiceArchetype && this.renderInvoiceObject(invoiceArchetype), emailArchetype && this.renderEmailObject(emailArchetype), !docArchetype && !invoiceArchetype && !emailArchetype && this.items.map(item => this.renderItem(item))), this.renderImageModal()));
|
|
363
363
|
}
|
|
364
364
|
static get is() { return "mrd-layout-section"; }
|
|
365
365
|
static get encapsulation() { return "scoped"; }
|
|
@@ -121,14 +121,14 @@ export class MrdMergeView {
|
|
|
121
121
|
var _a, _b;
|
|
122
122
|
let stepContent;
|
|
123
123
|
if (this.step === 'search') {
|
|
124
|
-
stepContent = (h(MergeSearchStep, { key: '
|
|
124
|
+
stepContent = (h(MergeSearchStep, { key: 'b965c21176faf7844e58cb156958fa1305d07cdc', locale: this.locale, searchQuery: this.searchQuery, searchResults: this.searchResults, isLoading: this.isLoading, onSearchInput: this.handleSearchInput, onSelect: this.handleSelect }));
|
|
125
125
|
}
|
|
126
126
|
else {
|
|
127
127
|
const diff = diffFields(this.fields, this.currentRecord, this.candidate);
|
|
128
128
|
const bLabel = candidateLabel(this.candidate);
|
|
129
129
|
stepContent = this.step === 'compare' ? (h(MergeCompareStep, { locale: this.locale, currentLabel: this.currentLabel, candidateLabel: bLabel, conflicts: diff.conflicts, autoFilled: diff.autoFilled, recordA: this.currentRecord, recordB: (_a = this.candidate) !== null && _a !== void 0 ? _a : {}, resolutions: this.resolutions, openHistoryKey: this.openHistoryKey, onResolve: this.handleResolve, onToggleHistory: this.handleToggleHistory, onChangeCandidate: this.handleChangeCandidate, onContinue: this.handleContinue })) : (h(MergeConfirmStep, { locale: this.locale, candidateLabel: bLabel, conflicts: diff.conflicts, autoFilled: diff.autoFilled, resolutions: this.resolutions, recordB: (_b = this.candidate) !== null && _b !== void 0 ? _b : {}, openHistoryKey: this.openHistoryKey, onToggleHistory: this.handleToggleHistory, onBack: this.handleBack, onConfirm: this.handleConfirm }));
|
|
130
130
|
}
|
|
131
|
-
return (h(Host, { key: '
|
|
131
|
+
return (h(Host, { key: 'e9cffda6c5cff51f802b044f3d8e417df83b7846' }, h("div", { key: '26690ef2db7489cbf7994191ad19491a0fdd7002', class: "mrd-merge-view" }, stepContent)));
|
|
132
132
|
}
|
|
133
133
|
static get is() { return "mrd-merge-view"; }
|
|
134
134
|
static get encapsulation() { return "scoped"; }
|
|
@@ -134,7 +134,7 @@ async function initDetailViewTab() {
|
|
|
134
134
|
table.item = window.EXAMPLE_COMPANY_VIEW_ITEM;
|
|
135
135
|
table.totalElements = window.EXAMPLE_COMPANIES.length;
|
|
136
136
|
table.pageSize = 20;
|
|
137
|
-
table.locale =
|
|
137
|
+
table.locale = _locale;
|
|
138
138
|
|
|
139
139
|
// Register before init(): init() emits mrdLoadPage for page 0 itself.
|
|
140
140
|
table.addEventListener('mrdLoadPage', async (e) => {
|
|
@@ -174,7 +174,7 @@ function showCompanyDetail(row) {
|
|
|
174
174
|
const section = document.createElement('mrd-layout-section');
|
|
175
175
|
section.items = layout.items;
|
|
176
176
|
section.data = company;
|
|
177
|
-
section.locale =
|
|
177
|
+
section.locale = _locale;
|
|
178
178
|
|
|
179
179
|
section.addEventListener('mrdNavigate', (e) => {
|
|
180
180
|
logEvent('mrdNavigate', e.detail);
|
|
@@ -1136,16 +1136,57 @@ customElements.whenDefined('mrd-form').then(() => {
|
|
|
1136
1136
|
form.addEventListener('mrdFetchAll', (e) => { console.log('[mrdFetchAll]', e.detail); logEvent('mrdFetchAll', e.detail); });
|
|
1137
1137
|
});
|
|
1138
1138
|
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1139
|
+
/* =====================================================================
|
|
1140
|
+
LOCALE CONTROL
|
|
1141
|
+
===================================================================== */
|
|
1142
|
+
|
|
1143
|
+
/** Every component that takes a `locale` prop — the control drives all of them. */
|
|
1144
|
+
const LOCALE_HOSTS = [
|
|
1145
|
+
'mrd-form', 'mrd-layout-section', 'mrd-table', 'mrd-merge-view',
|
|
1146
|
+
'mrd-document-container', 'mrd-document-list', 'mrd-document-view',
|
|
1147
|
+
'mrd-invoice-view', 'mrd-email-view',
|
|
1148
|
+
].join(', ');
|
|
1149
|
+
|
|
1150
|
+
/** Single source of truth: push the selected locale into everything on the page. */
|
|
1151
|
+
function applyLocale(locale) {
|
|
1152
|
+
_locale = locale;
|
|
1153
|
+
document.querySelectorAll(LOCALE_HOSTS).forEach((el) => { el.locale = locale; });
|
|
1154
|
+
renderLocaleHint();
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
/**
|
|
1158
|
+
* Shows what the selected locale does next to what the browser would do on its
|
|
1159
|
+
* own. Those two differ exactly where the `locale` prop earns its keep — the
|
|
1160
|
+
* date fields format by prop, a native date input would follow the browser.
|
|
1161
|
+
*/
|
|
1162
|
+
function renderLocaleHint() {
|
|
1163
|
+
const hint = document.getElementById('locale-hint');
|
|
1164
|
+
if (!hint) return;
|
|
1165
|
+
const sample = new Date(2026, 6, 6, 14, 30); // 6 July — day > 12 keeps d/m order readable
|
|
1166
|
+
const format = (loc) => new Intl.DateTimeFormat(loc, {
|
|
1167
|
+
year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit',
|
|
1168
|
+
}).format(sample);
|
|
1169
|
+
|
|
1170
|
+
hint.innerHTML =
|
|
1171
|
+
`<span>prop <code>${escHtml(_locale)}</code> → <b>${escHtml(format(_locale))}</b></span>` +
|
|
1172
|
+
`<span>browser <code>${escHtml(navigator.language)}</code> → <b>${escHtml(format(navigator.language))}</b></span>`;
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
function initLocaleControl() {
|
|
1176
|
+
const select = document.getElementById('locale-select');
|
|
1177
|
+
// The browser locale is worth testing too, even when it is not in the list.
|
|
1178
|
+
if (![...select.options].some((o) => o.value === _locale)) {
|
|
1179
|
+
const option = document.createElement('option');
|
|
1180
|
+
option.value = _locale;
|
|
1181
|
+
option.textContent = `🖥️ Browser (${_locale})`;
|
|
1182
|
+
select.insertBefore(option, select.firstChild);
|
|
1183
|
+
}
|
|
1184
|
+
select.value = _locale;
|
|
1185
|
+
select.addEventListener('change', (e) => applyLocale(e.target.value));
|
|
1186
|
+
applyLocale(_locale);
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
initLocaleControl();
|
|
1149
1190
|
|
|
1150
1191
|
document.getElementById('btn-inject-results').addEventListener('click', () => {
|
|
1151
1192
|
const relationField = document.querySelector('mrd-relation-field');
|
|
@@ -1170,7 +1211,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
|
1170
1211
|
const ftSection = document.getElementById('field-types-section');
|
|
1171
1212
|
ftSection.items = window.EXAMPLE_FIELD_TYPES_ITEMS;
|
|
1172
1213
|
ftSection.data = window.EXAMPLE_FIELD_TYPES_DATA;
|
|
1173
|
-
ftSection.locale =
|
|
1214
|
+
ftSection.locale = _locale;
|
|
1174
1215
|
|
|
1175
1216
|
// Simulate host resolving a signed URL for IMAGE fields (thumbnail on load).
|
|
1176
1217
|
ftSection.addEventListener('mrdLoadImage', (e) => {
|
|
@@ -1197,6 +1238,10 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|
|
1197
1238
|
ftSection.setSearchResults(mock, dataClass);
|
|
1198
1239
|
});
|
|
1199
1240
|
|
|
1241
|
+
// Re-apply once the whole page is parsed, so components mounted in markup
|
|
1242
|
+
// (and any upgraded after the control ran) all agree on the locale.
|
|
1243
|
+
applyLocale(_locale);
|
|
1244
|
+
|
|
1200
1245
|
authRestoreSession();
|
|
1201
1246
|
await authHandleCallback();
|
|
1202
1247
|
|
|
@@ -53,6 +53,166 @@ export function formatTime(value, locale) {
|
|
|
53
53
|
date.setHours(hours, minutes, 0, 0);
|
|
54
54
|
return new Intl.DateTimeFormat(locale, { hour: '2-digit', minute: '2-digit' }).format(date);
|
|
55
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* Locale-aware date input support.
|
|
58
|
+
*
|
|
59
|
+
* A native <input type="date"> always displays in the browser/OS locale, so the
|
|
60
|
+
* date fields render a plain text input instead and use these helpers to format
|
|
61
|
+
* and parse the value in the locale the host passed down — the same approach
|
|
62
|
+
* mrd-number-field takes with formatNumber / parseLocalizedNumber.
|
|
63
|
+
*/
|
|
64
|
+
/** 31 December 2026, 13:45 — day > 12 so day/month order is unambiguous. */
|
|
65
|
+
const PATTERN_SAMPLE = new Date(2026, 11, 31, 13, 45, 0);
|
|
66
|
+
function dateTimeParts(locale, withTime) {
|
|
67
|
+
const options = { year: 'numeric', month: '2-digit', day: '2-digit' };
|
|
68
|
+
if (withTime) {
|
|
69
|
+
options.hour = '2-digit';
|
|
70
|
+
options.minute = '2-digit';
|
|
71
|
+
}
|
|
72
|
+
return new Intl.DateTimeFormat(locale, options).formatToParts(PATTERN_SAMPLE);
|
|
73
|
+
}
|
|
74
|
+
/** Order in which day/month/year appear for a locale, e.g. ['day','month','year'] for nl-NL. */
|
|
75
|
+
function datePartOrder(locale) {
|
|
76
|
+
const order = dateTimeParts(locale, false)
|
|
77
|
+
.filter(p => p.type === 'day' || p.type === 'month' || p.type === 'year')
|
|
78
|
+
.map(p => p.type);
|
|
79
|
+
return order.length === 3 ? order : ['day', 'month', 'year'];
|
|
80
|
+
}
|
|
81
|
+
/** The locale's am/pm markers, so 12-hour input can be parsed back. */
|
|
82
|
+
function dayPeriodMarkers(locale) {
|
|
83
|
+
const marker = (hour) => {
|
|
84
|
+
var _a, _b;
|
|
85
|
+
return (_b = (_a = new Intl.DateTimeFormat(locale, { hour: 'numeric', hour12: true })
|
|
86
|
+
.formatToParts(new Date(2026, 0, 1, hour))
|
|
87
|
+
.find(p => p.type === 'dayPeriod')) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : '';
|
|
88
|
+
};
|
|
89
|
+
return { am: marker(9), pm: marker(21) };
|
|
90
|
+
}
|
|
91
|
+
/** Arabic-Indic and extended Arabic-Indic digits → ASCII, so typed input parses everywhere. */
|
|
92
|
+
function toLatinDigits(str) {
|
|
93
|
+
return str.replace(/[٠-٩۰-۹]/g, d => {
|
|
94
|
+
const code = d.charCodeAt(0);
|
|
95
|
+
return String(code >= 0x06f0 ? code - 0x06f0 : code - 0x0660);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
function pad(n, size = 2) {
|
|
99
|
+
return String(n).padStart(size, '0');
|
|
100
|
+
}
|
|
101
|
+
/** Two-digit years: < 70 → 20xx, otherwise 19xx. */
|
|
102
|
+
function expandYear(value, digits) {
|
|
103
|
+
if (digits > 2)
|
|
104
|
+
return value;
|
|
105
|
+
return value < 70 ? 2000 + value : 1900 + value;
|
|
106
|
+
}
|
|
107
|
+
function isValidYmd(year, month, day) {
|
|
108
|
+
if (year < 1 || month < 1 || month > 12 || day < 1)
|
|
109
|
+
return false;
|
|
110
|
+
return day <= new Date(year, month, 0).getDate();
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Placeholder showing the locale's date order, e.g. 'dd-mm-jjjj' (nl-NL) or
|
|
114
|
+
* 'mm/dd/yyyy' (en-US). Pass `hour`/`minute` tokens to include the time part.
|
|
115
|
+
*/
|
|
116
|
+
export function localeDatePattern(locale, tokens) {
|
|
117
|
+
const withTime = !!(tokens.hour && tokens.minute);
|
|
118
|
+
return dateTimeParts(locale, withTime)
|
|
119
|
+
.map(part => {
|
|
120
|
+
var _a, _b;
|
|
121
|
+
switch (part.type) {
|
|
122
|
+
case 'day': return tokens.day;
|
|
123
|
+
case 'month': return tokens.month;
|
|
124
|
+
case 'year': return tokens.year;
|
|
125
|
+
case 'hour': return (_a = tokens.hour) !== null && _a !== void 0 ? _a : '';
|
|
126
|
+
case 'minute': return (_b = tokens.minute) !== null && _b !== void 0 ? _b : '';
|
|
127
|
+
case 'dayPeriod': return 'AM';
|
|
128
|
+
case 'literal': return part.value;
|
|
129
|
+
default: return '';
|
|
130
|
+
}
|
|
131
|
+
})
|
|
132
|
+
.join('')
|
|
133
|
+
.trim();
|
|
134
|
+
}
|
|
135
|
+
/** Pulls day/month/year out of the number groups a user typed, per locale order. */
|
|
136
|
+
function ymdFromGroups(groups, locale) {
|
|
137
|
+
const order = datePartOrder(locale);
|
|
138
|
+
const values = {};
|
|
139
|
+
order.forEach((type, i) => (values[type] = groups[i]));
|
|
140
|
+
const year = expandYear(Number(values.year), values.year.length);
|
|
141
|
+
const month = Number(values.month);
|
|
142
|
+
const day = Number(values.day);
|
|
143
|
+
return isValidYmd(year, month, day) ? { year, month, day } : null;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Parses a date the user typed in their own locale format → 'YYYY-MM-DD'.
|
|
147
|
+
* Accepts any separator, one- or two-digit day/month, two-digit years, and
|
|
148
|
+
* plain ISO input (pasted values). Returns null when it is not a valid date.
|
|
149
|
+
*/
|
|
150
|
+
export function parseLocalizedDate(input, locale) {
|
|
151
|
+
const raw = toLatinDigits(String(input !== null && input !== void 0 ? input : '')).trim();
|
|
152
|
+
if (!raw)
|
|
153
|
+
return null;
|
|
154
|
+
const groups = raw.match(/\d+/g);
|
|
155
|
+
if (!groups || groups.length < 3)
|
|
156
|
+
return null;
|
|
157
|
+
const iso = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(raw);
|
|
158
|
+
const parsed = iso
|
|
159
|
+
? (isValidYmd(+iso[1], +iso[2], +iso[3]) ? { year: +iso[1], month: +iso[2], day: +iso[3] } : null)
|
|
160
|
+
: ymdFromGroups(groups.slice(0, 3), locale);
|
|
161
|
+
if (!parsed)
|
|
162
|
+
return null;
|
|
163
|
+
return `${pad(parsed.year, 4)}-${pad(parsed.month)}-${pad(parsed.day)}`;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Parses a date+time the user typed in their own locale format →
|
|
167
|
+
* 'YYYY-MM-DDTHH:mm' in local time (the shape mrd-datetime-field converts to
|
|
168
|
+
* UTC before emitting). A missing time defaults to 00:00; am/pm is recognised
|
|
169
|
+
* both in English and in the locale's own markers.
|
|
170
|
+
*/
|
|
171
|
+
export function parseLocalizedDateTime(input, locale) {
|
|
172
|
+
const raw = toLatinDigits(String(input !== null && input !== void 0 ? input : '')).trim();
|
|
173
|
+
if (!raw)
|
|
174
|
+
return null;
|
|
175
|
+
const groups = raw.match(/\d+/g);
|
|
176
|
+
if (!groups || groups.length < 3)
|
|
177
|
+
return null;
|
|
178
|
+
const iso = /^(\d{4})-(\d{1,2})-(\d{1,2})(?:[T ]|$)/.exec(raw);
|
|
179
|
+
const date = iso
|
|
180
|
+
? (isValidYmd(+iso[1], +iso[2], +iso[3]) ? { year: +iso[1], month: +iso[2], day: +iso[3] } : null)
|
|
181
|
+
: ymdFromGroups(groups.slice(0, 3), locale);
|
|
182
|
+
if (!date)
|
|
183
|
+
return null;
|
|
184
|
+
let hour = groups.length > 3 ? Number(groups[3]) : 0;
|
|
185
|
+
const minute = groups.length > 4 ? Number(groups[4]) : 0;
|
|
186
|
+
const lower = raw.toLowerCase();
|
|
187
|
+
const { am, pm } = dayPeriodMarkers(locale);
|
|
188
|
+
const isPm = /p\.?\s?m\.?/.test(lower) || (!!pm && lower.includes(pm.toLowerCase()));
|
|
189
|
+
const isAm = /a\.?\s?m\.?/.test(lower) || (!!am && lower.includes(am.toLowerCase()));
|
|
190
|
+
if (isPm && hour < 12)
|
|
191
|
+
hour += 12;
|
|
192
|
+
if (isAm && hour === 12)
|
|
193
|
+
hour = 0;
|
|
194
|
+
if (hour > 23 || minute > 59)
|
|
195
|
+
return null;
|
|
196
|
+
return `${pad(date.year, 4)}-${pad(date.month)}-${pad(date.day)}T${pad(hour)}:${pad(minute)}`;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* 'YYYY-MM-DD' → localized display string. Parsed as a *local* date, unlike
|
|
200
|
+
* formatDate(), which would read a date-only string as UTC midnight and shift
|
|
201
|
+
* the day in negative-offset timezones.
|
|
202
|
+
*/
|
|
203
|
+
export function formatIsoDate(iso, locale) {
|
|
204
|
+
const m = /^(\d{4})-(\d{2})-(\d{2})/.exec(String(iso !== null && iso !== void 0 ? iso : ''));
|
|
205
|
+
if (!m)
|
|
206
|
+
return '';
|
|
207
|
+
return formatDate(new Date(+m[1], +m[2] - 1, +m[3]), locale);
|
|
208
|
+
}
|
|
209
|
+
/** 'YYYY-MM-DDTHH:mm' in local time → localized display string. */
|
|
210
|
+
export function formatLocalDateTime(local, locale) {
|
|
211
|
+
const m = /^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})/.exec(String(local !== null && local !== void 0 ? local : ''));
|
|
212
|
+
if (!m)
|
|
213
|
+
return '';
|
|
214
|
+
return formatDateTime(new Date(+m[1], +m[2] - 1, +m[3], +m[4], +m[5]), locale);
|
|
215
|
+
}
|
|
56
216
|
export function parseLocalizedNumber(str, locale) {
|
|
57
217
|
var _a, _b, _c, _d;
|
|
58
218
|
if (!str || !str.trim())
|