@mmlogic/components 0.3.10 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/dist/cjs/{index-BPj2cBXs.js → index-CAzwGt9u.js} +38 -0
  2. package/dist/cjs/loader.cjs.js +2 -2
  3. package/dist/cjs/mosterdcomponents.cjs.js +2 -2
  4. package/dist/cjs/mrd-boolean-field_23.cjs.entry.js +1280 -1073
  5. package/dist/collection/collection-manifest.json +23 -23
  6. package/dist/collection/components/{mrd-document-container/mrd-document-container.scss → documents/mrd-document-container/mrd-document-container.css} +3 -3
  7. package/dist/collection/components/{mrd-document-container → documents/mrd-document-container}/mrd-document-container.js +54 -8
  8. package/dist/collection/components/documents/mrd-document-list/folder-tree.js +109 -0
  9. package/dist/collection/components/{mrd-document-list/mrd-document-list.scss → documents/mrd-document-list/mrd-document-list.css} +17 -4
  10. package/dist/collection/components/{mrd-document-list → documents/mrd-document-list}/mrd-document-list.js +166 -237
  11. package/dist/collection/components/documents/mrd-document-list/tree-view.js +75 -0
  12. package/dist/collection/components/{mrd-document-view/mrd-document-view.scss → documents/mrd-document-view/mrd-document-view.css} +1 -1
  13. package/dist/collection/components/{mrd-document-view → documents/mrd-document-view}/mrd-document-view.js +4 -4
  14. package/dist/collection/components/fields/field-helpers.js +17 -0
  15. package/dist/collection/components/fields/file-upload-common.js +38 -0
  16. package/dist/collection/components/{mrd-boolean-field/mrd-boolean-field.scss → fields/mrd-boolean-field/mrd-boolean-field.css} +3 -3
  17. package/dist/collection/components/{mrd-boolean-field → fields/mrd-boolean-field}/mrd-boolean-field.js +1 -1
  18. package/dist/collection/components/{mrd-currency-field/mrd-currency-field.scss → fields/mrd-currency-field/mrd-currency-field.css} +11 -9
  19. package/dist/collection/components/{mrd-currency-field → fields/mrd-currency-field}/mrd-currency-field.js +7 -13
  20. package/dist/collection/components/{mrd-date-field/mrd-date-field.scss → fields/mrd-date-field/mrd-date-field.css} +8 -10
  21. package/dist/collection/components/{mrd-date-field → fields/mrd-date-field}/mrd-date-field.js +3 -10
  22. package/dist/collection/components/{mrd-datetime-field/mrd-datetime-field.scss → fields/mrd-datetime-field/mrd-datetime-field.css} +8 -10
  23. package/dist/collection/components/{mrd-datetime-field → fields/mrd-datetime-field}/mrd-datetime-field.js +3 -10
  24. package/dist/collection/components/{mrd-email-field/mrd-email-field.scss → fields/mrd-email-field/mrd-email-field.css} +2 -11
  25. package/dist/collection/components/{mrd-email-field → fields/mrd-email-field}/mrd-email-field.js +6 -13
  26. package/dist/collection/components/{mrd-file-field/mrd-file-field.scss → fields/mrd-file-field/mrd-file-field.css} +19 -24
  27. package/dist/collection/components/{mrd-file-field → fields/mrd-file-field}/mrd-file-field.js +13 -24
  28. package/dist/collection/components/{mrd-hyperlink-field/mrd-hyperlink-field.scss → fields/mrd-hyperlink-field/mrd-hyperlink-field.css} +7 -16
  29. package/dist/collection/components/{mrd-hyperlink-field → fields/mrd-hyperlink-field}/mrd-hyperlink-field.js +9 -15
  30. package/dist/collection/components/{mrd-image-field/mrd-image-field.scss → fields/mrd-image-field/mrd-image-field.css} +15 -24
  31. package/dist/collection/components/{mrd-image-field → fields/mrd-image-field}/mrd-image-field.js +13 -28
  32. package/dist/collection/components/{mrd-list-field/mrd-list-field.scss → fields/mrd-list-field/mrd-list-field.css} +18 -21
  33. package/dist/collection/components/{mrd-list-field → fields/mrd-list-field}/mrd-list-field.js +10 -25
  34. package/dist/collection/components/{mrd-longtext-field/mrd-longtext-field.scss → fields/mrd-longtext-field/mrd-longtext-field.css} +21 -18
  35. package/dist/collection/components/{mrd-longtext-field → fields/mrd-longtext-field}/mrd-longtext-field.js +3 -10
  36. package/dist/collection/components/{mrd-number-field/mrd-number-field.scss → fields/mrd-number-field/mrd-number-field.css} +9 -10
  37. package/dist/collection/components/{mrd-number-field → fields/mrd-number-field}/mrd-number-field.js +7 -6
  38. package/dist/collection/components/{mrd-relation-field/mrd-relation-field.scss → fields/mrd-relation-field/mrd-relation-field.css} +61 -59
  39. package/dist/collection/components/{mrd-relation-field → fields/mrd-relation-field}/mrd-relation-field.js +16 -26
  40. package/dist/collection/components/{mrd-secret-field/mrd-secret-field.scss → fields/mrd-secret-field/mrd-secret-field.css} +7 -10
  41. package/dist/collection/components/{mrd-secret-field → fields/mrd-secret-field}/mrd-secret-field.js +4 -11
  42. package/dist/collection/components/{mrd-text-field/mrd-text-field.scss → fields/mrd-text-field/mrd-text-field.css} +2 -11
  43. package/dist/collection/components/{mrd-text-field → fields/mrd-text-field}/mrd-text-field.js +3 -10
  44. package/dist/collection/components/{mrd-textarea-field/mrd-textarea-field.scss → fields/mrd-textarea-field/mrd-textarea-field.css} +7 -10
  45. package/dist/collection/components/{mrd-textarea-field → fields/mrd-textarea-field}/mrd-textarea-field.js +3 -9
  46. package/dist/collection/components/{mrd-time-field/mrd-time-field.scss → fields/mrd-time-field/mrd-time-field.css} +8 -10
  47. package/dist/collection/components/{mrd-time-field → fields/mrd-time-field}/mrd-time-field.js +3 -10
  48. package/dist/collection/components/{mrd-field/mrd-field.scss → form/mrd-field/mrd-field.css} +1 -1
  49. package/dist/collection/components/{mrd-field → form/mrd-field}/mrd-field.js +3 -3
  50. package/dist/collection/components/{mrd-form/mrd-form.scss → form/mrd-form/mrd-form.css} +1 -1
  51. package/dist/collection/components/{mrd-form → form/mrd-form}/mrd-form.js +5 -5
  52. package/dist/collection/components/layout/mrd-layout-section/field-value.js +111 -0
  53. package/dist/collection/components/layout/mrd-layout-section/layout-helpers.js +29 -0
  54. package/dist/collection/components/{mrd-layout-section/mrd-layout-section.scss → layout/mrd-layout-section/mrd-layout-section.css} +4 -4
  55. package/dist/collection/components/{mrd-layout-section → layout/mrd-layout-section}/mrd-layout-section.js +58 -133
  56. package/dist/collection/components/{mrd-table/mrd-table.scss → table/mrd-table/mrd-table.css} +11 -13
  57. package/dist/collection/components/{mrd-table → table/mrd-table}/mrd-table.js +111 -439
  58. package/dist/collection/components/table/mrd-table/table-filter-popup.js +85 -0
  59. package/dist/collection/components/table/mrd-table/table-parts.js +110 -0
  60. package/dist/collection/components/table/mrd-table/table-query.js +178 -0
  61. package/dist/collection/components/table/mrd-table/virtual-scroll.js +49 -0
  62. package/dist/collection/dev/app.js +19 -18
  63. package/dist/collection/dev/example-data.js +58 -43
  64. package/dist/collection/utils/i18n.js +10 -0
  65. package/dist/collection/utils/query-params.js +43 -0
  66. package/dist/components/field-helpers.js +1 -0
  67. package/dist/components/file-upload-common.js +1 -0
  68. package/dist/components/i18n.js +1 -1
  69. package/dist/components/mrd-boolean-field2.js +1 -1
  70. package/dist/components/mrd-currency-field2.js +1 -1
  71. package/dist/components/mrd-date-field2.js +1 -1
  72. package/dist/components/mrd-datetime-field2.js +1 -1
  73. package/dist/components/mrd-document-container2.js +1 -1
  74. package/dist/components/mrd-document-list2.js +1 -1
  75. package/dist/components/mrd-document-view2.js +1 -1
  76. package/dist/components/mrd-email-field2.js +1 -1
  77. package/dist/components/mrd-file-field2.js +1 -1
  78. package/dist/components/mrd-form.js +1 -1
  79. package/dist/components/mrd-hyperlink-field2.js +1 -1
  80. package/dist/components/mrd-image-field2.js +1 -1
  81. package/dist/components/mrd-layout-section.js +1 -1
  82. package/dist/components/mrd-list-field2.js +1 -1
  83. package/dist/components/mrd-longtext-field2.js +1 -1
  84. package/dist/components/mrd-number-field2.js +1 -1
  85. package/dist/components/mrd-relation-field2.js +1 -1
  86. package/dist/components/mrd-secret-field2.js +1 -1
  87. package/dist/components/mrd-table2.js +1 -1
  88. package/dist/components/mrd-text-field2.js +1 -1
  89. package/dist/components/mrd-textarea-field2.js +1 -1
  90. package/dist/components/mrd-time-field2.js +1 -1
  91. package/dist/components/query-params.js +1 -0
  92. package/dist/esm/{index-_tsCCkAi.js → index-DiSEJMA8.js} +38 -1
  93. package/dist/esm/loader.js +3 -3
  94. package/dist/esm/mosterdcomponents.js +3 -3
  95. package/dist/esm/mrd-boolean-field_23.entry.js +1280 -1073
  96. package/dist/mosterdcomponents/mosterdcomponents.css +1 -1
  97. package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
  98. package/dist/mosterdcomponents/p-9b3c0917.entry.js +1 -0
  99. package/dist/mosterdcomponents/p-DiSEJMA8.js +2 -0
  100. package/dist/types/components/{mrd-document-container → documents/mrd-document-container}/mrd-document-container.d.ts +7 -2
  101. package/dist/types/components/documents/mrd-document-list/folder-tree.d.ts +66 -0
  102. package/dist/types/components/{mrd-document-list → documents/mrd-document-list}/mrd-document-list.d.ts +28 -38
  103. package/dist/types/components/documents/mrd-document-list/tree-view.d.ts +32 -0
  104. package/dist/types/components/{mrd-document-view → documents/mrd-document-view}/mrd-document-view.d.ts +2 -2
  105. package/dist/types/components/fields/field-helpers.d.ts +18 -0
  106. package/dist/types/components/fields/file-upload-common.d.ts +18 -0
  107. package/dist/types/components/{mrd-boolean-field → fields/mrd-boolean-field}/mrd-boolean-field.d.ts +1 -1
  108. package/dist/types/components/{mrd-currency-field → fields/mrd-currency-field}/mrd-currency-field.d.ts +2 -2
  109. package/dist/types/components/{mrd-date-field → fields/mrd-date-field}/mrd-date-field.d.ts +1 -1
  110. package/dist/types/components/{mrd-datetime-field → fields/mrd-datetime-field}/mrd-datetime-field.d.ts +1 -1
  111. package/dist/types/components/{mrd-email-field → fields/mrd-email-field}/mrd-email-field.d.ts +1 -1
  112. package/dist/types/components/{mrd-file-field → fields/mrd-file-field}/mrd-file-field.d.ts +2 -4
  113. package/dist/types/components/{mrd-hyperlink-field → fields/mrd-hyperlink-field}/mrd-hyperlink-field.d.ts +2 -2
  114. package/dist/types/components/{mrd-image-field → fields/mrd-image-field}/mrd-image-field.d.ts +2 -4
  115. package/dist/types/components/{mrd-list-field → fields/mrd-list-field}/mrd-list-field.d.ts +2 -2
  116. package/dist/types/components/{mrd-longtext-field → fields/mrd-longtext-field}/mrd-longtext-field.d.ts +1 -1
  117. package/dist/types/components/{mrd-number-field → fields/mrd-number-field}/mrd-number-field.d.ts +2 -2
  118. package/dist/types/components/{mrd-relation-field → fields/mrd-relation-field}/mrd-relation-field.d.ts +2 -2
  119. package/dist/types/components/{mrd-secret-field → fields/mrd-secret-field}/mrd-secret-field.d.ts +1 -1
  120. package/dist/types/components/{mrd-text-field → fields/mrd-text-field}/mrd-text-field.d.ts +1 -1
  121. package/dist/types/components/{mrd-textarea-field → fields/mrd-textarea-field}/mrd-textarea-field.d.ts +1 -1
  122. package/dist/types/components/{mrd-time-field → fields/mrd-time-field}/mrd-time-field.d.ts +1 -1
  123. package/dist/types/components/{mrd-field → form/mrd-field}/mrd-field.d.ts +2 -2
  124. package/dist/types/components/{mrd-form → form/mrd-form}/mrd-form.d.ts +2 -2
  125. package/dist/types/components/layout/mrd-layout-section/field-value.d.ts +22 -0
  126. package/dist/types/components/layout/mrd-layout-section/layout-helpers.d.ts +8 -0
  127. package/dist/types/components/{mrd-layout-section → layout/mrd-layout-section}/mrd-layout-section.d.ts +4 -8
  128. package/dist/types/components/{mrd-table → table/mrd-table}/mrd-table.d.ts +6 -13
  129. package/dist/types/components/table/mrd-table/table-filter-popup.d.ts +35 -0
  130. package/dist/types/components/table/mrd-table/table-parts.d.ts +61 -0
  131. package/dist/types/components/table/mrd-table/table-query.d.ts +50 -0
  132. package/dist/types/components/table/mrd-table/virtual-scroll.d.ts +26 -0
  133. package/dist/types/components.d.ts +36 -5
  134. package/dist/types/types/client-layout.d.ts +5 -0
  135. package/dist/types/utils/query-params.d.ts +14 -0
  136. package/package.json +7 -2
  137. package/dist/components/validation.js +0 -1
  138. package/dist/mosterdcomponents/cell-renderer-B-AJDBcj.js.map +0 -1
  139. package/dist/mosterdcomponents/client-layout-ChqRA3AF.js.map +0 -1
  140. package/dist/mosterdcomponents/format-BAfsQfy1.js.map +0 -1
  141. package/dist/mosterdcomponents/i18n-s1XrKcD2.js.map +0 -1
  142. package/dist/mosterdcomponents/index-DkY-NQj0.js.map +0 -1
  143. package/dist/mosterdcomponents/index-DwF_Sp__.js.map +0 -1
  144. package/dist/mosterdcomponents/index.esm.js.map +0 -1
  145. package/dist/mosterdcomponents/mosterdcomponents.esm.js.map +0 -1
  146. package/dist/mosterdcomponents/p-69452249.entry.js +0 -1
  147. package/dist/mosterdcomponents/p-_tsCCkAi.js +0 -2
  148. package/dist/mosterdcomponents/quill-C9pgw_k-.js.map +0 -1
  149. package/dist/mosterdcomponents/validation-Br9k2Ztw.js.map +0 -1
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-BPj2cBXs.js');
3
+ var index = require('./index-CAzwGt9u.js');
4
4
  var index$1 = require('./index.cjs.js');
5
5
 
6
- const mrdBooleanFieldScss = () => `.sc-mrd-boolean-field-h{display:block}.mrd-boolean-field.sc-mrd-boolean-field{display:flex;align-items:center;width:100%}.mrd-boolean-field__toggle-label.sc-mrd-boolean-field{display:flex;align-items:center;gap:var(--mrd-space-3);cursor:pointer;user-select:none}.mrd-boolean-field__checkbox.sc-mrd-boolean-field{position:absolute;opacity:0;width:0;height:0;pointer-events:none}.mrd-boolean-field__checkbox.sc-mrd-boolean-field:checked+.mrd-boolean-field__toggle.sc-mrd-boolean-field{background-color:var(--mrd-color-primary)}.mrd-boolean-field__checkbox.sc-mrd-boolean-field:checked+.mrd-boolean-field__toggle.sc-mrd-boolean-field::after{transform:translateX(20px)}.mrd-boolean-field__checkbox.sc-mrd-boolean-field:focus+.mrd-boolean-field__toggle.sc-mrd-boolean-field{box-shadow:var(--mrd-shadow-focus)}.mrd-boolean-field__checkbox.sc-mrd-boolean-field:disabled+.mrd-boolean-field__toggle.sc-mrd-boolean-field{opacity:0.5;cursor:not-allowed}.mrd-boolean-field__toggle.sc-mrd-boolean-field{position:relative;display:inline-block;width:44px;height:24px;background-color:var(--mrd-color-neutral-300);border-radius:var(--mrd-border-radius-full);transition:background-color var(--mrd-transition);flex-shrink:0}.mrd-boolean-field__toggle.sc-mrd-boolean-field::after{content:'';position:absolute;top:2px;left:2px;width:20px;height:20px;background-color:var(--mrd-color-white);border-radius:50%;transition:transform var(--mrd-transition);box-shadow:var(--mrd-shadow-sm)}.mrd-boolean-field__text.sc-mrd-boolean-field{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-color-neutral-800)}.mrd-boolean-field__text--required.sc-mrd-boolean-field::after{content:' *';color:var(--mrd-color-danger)}`;
6
+ const mrdBooleanFieldCss = () => `.sc-mrd-boolean-field-h{display:block}.mrd-boolean-field.sc-mrd-boolean-field{display:flex;align-items:center;width:100%}.mrd-boolean-field__toggle-label.sc-mrd-boolean-field{display:flex;align-items:center;gap:var(--mrd-space-3);cursor:pointer;user-select:none}.mrd-boolean-field__checkbox.sc-mrd-boolean-field{position:absolute;opacity:0;width:0;height:0;pointer-events:none}.mrd-boolean-field__checkbox.sc-mrd-boolean-field:checked+.mrd-boolean-field__toggle.sc-mrd-boolean-field{background-color:var(--mrd-color-primary)}.mrd-boolean-field__checkbox.sc-mrd-boolean-field:checked+.mrd-boolean-field__toggle.sc-mrd-boolean-field::after{transform:translateX(20px)}.mrd-boolean-field__checkbox.sc-mrd-boolean-field:focus+.mrd-boolean-field__toggle.sc-mrd-boolean-field{box-shadow:var(--mrd-shadow-focus)}.mrd-boolean-field__checkbox.sc-mrd-boolean-field:disabled+.mrd-boolean-field__toggle.sc-mrd-boolean-field{opacity:0.5;cursor:not-allowed}.mrd-boolean-field__toggle.sc-mrd-boolean-field{position:relative;display:inline-block;width:44px;height:24px;background-color:var(--mrd-color-neutral-300);border-radius:var(--mrd-border-radius-full);transition:background-color var(--mrd-transition);flex-shrink:0}.mrd-boolean-field__toggle.sc-mrd-boolean-field::after{content:"";position:absolute;top:2px;left:2px;width:20px;height:20px;background-color:var(--mrd-color-white);border-radius:50%;transition:transform var(--mrd-transition);box-shadow:var(--mrd-shadow-sm)}.mrd-boolean-field__text.sc-mrd-boolean-field{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-color-neutral-800)}.mrd-boolean-field__text--required.sc-mrd-boolean-field::after{content:" *";color:var(--mrd-color-danger)}`;
7
7
 
8
8
  const MrdBooleanField = class {
9
9
  constructor(hostRef) {
@@ -29,10 +29,83 @@ const MrdBooleanField = class {
29
29
  this.checked = !!this.value;
30
30
  }
31
31
  render() {
32
- return (index.h(index.Host, { key: '38e65a1c7971912f8259d09281b272d7cbd446f2' }, index.h("div", { key: 'e10919998731d744cc2a13130c5f355c9b8fc9aa', class: "mrd-boolean-field" }, index.h("label", { key: 'db85a2c80cc62fdfd25237e3f5c7750bf1666819', class: "mrd-boolean-field__toggle-label" }, index.h("input", { key: 'cddd7004593fa4671abb89f4f805c4a009db99ef', class: "mrd-boolean-field__checkbox", type: "checkbox", name: this.name, checked: this.checked, disabled: this.disabled, onChange: this.handleChange, onBlur: this.handleBlur }), index.h("span", { key: 'f90f0ed6d74d6688e51b8d85a5397a0597d95ad8', class: "mrd-boolean-field__toggle", "aria-hidden": "true" }), this.label && (index.h("span", { key: '7e4582b1d9a5b08c00c220bec53baa6c14cbfe43', class: `mrd-boolean-field__text${this.required ? ' mrd-boolean-field__text--required' : ''}` }, this.label))))));
32
+ return (index.h(index.Host, { key: 'f7851813646d31c565c262bf3c8d4083177dd993' }, index.h("div", { key: '4b3c9f46e8b79bdc97ef5815afb85ba5ddde0c9a', class: "mrd-boolean-field" }, index.h("label", { key: 'f81fa28d5a79de0445c2c192352343f0807609a1', class: "mrd-boolean-field__toggle-label" }, index.h("input", { key: '510a4f5533cbe2741b8df34cb64fc739475a26cf', class: "mrd-boolean-field__checkbox", type: "checkbox", name: this.name, checked: this.checked, disabled: this.disabled, onChange: this.handleChange, onBlur: this.handleBlur }), index.h("span", { key: '949e042c8af0f2872cf973a0d5407fce972eb240', class: "mrd-boolean-field__toggle", "aria-hidden": "true" }), this.label && (index.h("span", { key: 'e8c52b5820887b2a8ec9a20eb7e4116a528d27d4', class: `mrd-boolean-field__text${this.required ? ' mrd-boolean-field__text--required' : ''}` }, this.label))))));
33
33
  }
34
34
  };
35
- MrdBooleanField.style = mrdBooleanFieldScss();
35
+ MrdBooleanField.style = mrdBooleanFieldCss();
36
+
37
+ function formatNumber(value, locale, options) {
38
+ if (value === null || value === undefined || isNaN(value))
39
+ return '';
40
+ return new Intl.NumberFormat(locale, options).format(value);
41
+ }
42
+ function formatCurrency(amount, currency, locale) {
43
+ if (amount === null || amount === undefined || isNaN(amount))
44
+ return '';
45
+ return new Intl.NumberFormat(locale, {
46
+ style: 'currency',
47
+ currency,
48
+ minimumFractionDigits: 2,
49
+ maximumFractionDigits: 2,
50
+ }).format(amount);
51
+ }
52
+ function formatPercentage(value, locale, decimalPrecision = 2) {
53
+ if (value === null || value === undefined || isNaN(value))
54
+ return '';
55
+ return new Intl.NumberFormat(locale, {
56
+ style: 'percent',
57
+ minimumFractionDigits: decimalPrecision,
58
+ maximumFractionDigits: decimalPrecision,
59
+ }).format(value);
60
+ }
61
+ function formatDate(value, locale) {
62
+ if (!value)
63
+ return '';
64
+ const date = typeof value === 'string' ? new Date(value) : value;
65
+ if (isNaN(date.getTime()))
66
+ return '';
67
+ return new Intl.DateTimeFormat(locale, { year: 'numeric', month: '2-digit', day: '2-digit' }).format(date);
68
+ }
69
+ function formatDateTime(value, locale) {
70
+ if (!value)
71
+ return '';
72
+ const date = typeof value === 'string' ? new Date(value) : value;
73
+ if (isNaN(date.getTime()))
74
+ return '';
75
+ return new Intl.DateTimeFormat(locale, {
76
+ year: 'numeric',
77
+ month: '2-digit',
78
+ day: '2-digit',
79
+ hour: '2-digit',
80
+ minute: '2-digit',
81
+ }).format(date);
82
+ }
83
+ function formatTime(value, locale) {
84
+ if (!value)
85
+ return '';
86
+ // value is HH:MM or HH:MM:SS
87
+ const [hours, minutes] = value.split(':').map(Number);
88
+ const date = new Date();
89
+ date.setHours(hours, minutes, 0, 0);
90
+ return new Intl.DateTimeFormat(locale, { hour: '2-digit', minute: '2-digit' }).format(date);
91
+ }
92
+ function parseLocalizedNumber(str, locale) {
93
+ var _a, _b, _c, _d;
94
+ if (!str || !str.trim())
95
+ return null;
96
+ // Detect decimal and thousands separators from the locale
97
+ const parts = new Intl.NumberFormat(locale).formatToParts(1234567.89);
98
+ const groupSep = (_b = (_a = parts.find((p) => p.type === 'group')) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : ',';
99
+ const decimalSep = (_d = (_c = parts.find((p) => p.type === 'decimal')) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : '.';
100
+ // Remove group separators, replace decimal separator with '.'
101
+ const normalized = str
102
+ .replace(new RegExp(`\\${groupSep}`, 'g'), '')
103
+ .replace(new RegExp(`\\${decimalSep}`), '.')
104
+ .replace('%', '')
105
+ .trim();
106
+ const parsed = parseFloat(normalized);
107
+ return isNaN(parsed) ? null : parsed;
108
+ }
36
109
 
37
110
  const translations = {
38
111
  nl: {
@@ -49,6 +122,7 @@ const translations = {
49
122
  drop_file_here: 'Sleep bestand hierheen of',
50
123
  browse: 'bladeren',
51
124
  file_too_large: 'Bestand is te groot',
125
+ invalid_image: 'Selecteer een afbeeldingsbestand',
52
126
  search_results: 'Zoekresultaten',
53
127
  no_results: 'Geen resultaten gevonden',
54
128
  loading: 'Laden...',
@@ -105,6 +179,7 @@ const translations = {
105
179
  folder_name_placeholder: 'Foldernaam',
106
180
  folder_no_slash: "Een foldernaam mag geen '/' bevatten",
107
181
  folder_duplicate: 'Er bestaat al een folder met deze naam',
182
+ doc_empty_drop: 'Nog geen documenten — sleep bestanden hierheen',
108
183
  },
109
184
  en: {
110
185
  required: 'This field is required',
@@ -120,6 +195,7 @@ const translations = {
120
195
  drop_file_here: 'Drop file here or',
121
196
  browse: 'browse',
122
197
  file_too_large: 'File is too large',
198
+ invalid_image: 'Please select an image file',
123
199
  search_results: 'Search results',
124
200
  no_results: 'No results found',
125
201
  loading: 'Loading...',
@@ -176,6 +252,7 @@ const translations = {
176
252
  folder_name_placeholder: 'Folder name',
177
253
  folder_no_slash: "A folder name cannot contain '/'",
178
254
  folder_duplicate: 'A folder with this name already exists',
255
+ doc_empty_drop: 'No documents yet — drop files here',
179
256
  },
180
257
  ar: {
181
258
  required: 'هذا الحقل مطلوب',
@@ -191,6 +268,7 @@ const translations = {
191
268
  drop_file_here: 'اسحب الملف هنا أو',
192
269
  browse: 'تصفح',
193
270
  file_too_large: 'الملف كبير جداً',
271
+ invalid_image: 'يرجى اختيار ملف صورة',
194
272
  search_results: 'نتائج البحث',
195
273
  no_results: 'لم يتم العثور على نتائج',
196
274
  loading: 'جار التحميل...',
@@ -257,6 +335,7 @@ const translations = {
257
335
  drop_file_here: 'Déposez le fichier ici ou',
258
336
  browse: 'parcourir',
259
337
  file_too_large: 'Le fichier est trop volumineux',
338
+ invalid_image: 'Veuillez sélectionner un fichier image',
260
339
  search_results: 'Résultats de recherche',
261
340
  no_results: 'Aucun résultat trouvé',
262
341
  loading: 'Chargement...',
@@ -323,6 +402,7 @@ const translations = {
323
402
  drop_file_here: 'Datei hier ablegen oder',
324
403
  browse: 'durchsuchen',
325
404
  file_too_large: 'Datei ist zu groß',
405
+ invalid_image: 'Bitte eine Bilddatei auswählen',
326
406
  search_results: 'Suchergebnisse',
327
407
  no_results: 'Keine Ergebnisse gefunden',
328
408
  loading: 'Laden...',
@@ -389,6 +469,7 @@ const translations = {
389
469
  drop_file_here: 'Suelte el archivo aquí o',
390
470
  browse: 'explorar',
391
471
  file_too_large: 'El archivo es demasiado grande',
472
+ invalid_image: 'Seleccione un archivo de imagen',
392
473
  search_results: 'Resultados de búsqueda',
393
474
  no_results: 'No se encontraron resultados',
394
475
  loading: 'Cargando...',
@@ -455,6 +536,7 @@ const translations = {
455
536
  drop_file_here: 'Trascina il file qui o',
456
537
  browse: 'sfoglia',
457
538
  file_too_large: 'Il file è troppo grande',
539
+ invalid_image: 'Seleziona un file immagine',
458
540
  search_results: 'Risultati della ricerca',
459
541
  no_results: 'Nessun risultato trovato',
460
542
  loading: 'Caricamento...',
@@ -521,6 +603,7 @@ const translations = {
521
603
  drop_file_here: 'Перетягніть файл сюди або',
522
604
  browse: 'огляд',
523
605
  file_too_large: 'Файл занадто великий',
606
+ invalid_image: 'Будь ласка, виберіть файл зображення',
524
607
  search_results: 'Результати пошуку',
525
608
  no_results: 'Результатів не знайдено',
526
609
  loading: 'Завантаження...',
@@ -631,80 +714,22 @@ function validateNumber(value, dataType) {
631
714
  return true;
632
715
  }
633
716
 
634
- function formatNumber(value, locale, options) {
635
- if (value === null || value === undefined || isNaN(value))
636
- return '';
637
- return new Intl.NumberFormat(locale, options).format(value);
717
+ /**
718
+ * Shared building blocks for the leaf field components.
719
+ * `base` is the BEM block name, e.g. 'mrd-text-field'.
720
+ */
721
+ const FieldLabel = ({ base, label, required }) => label ? index.h("label", { class: `${base}__label${required ? ` ${base}__label--required` : ''}` }, label) : null;
722
+ const FieldError = ({ base, error }) => error ? index.h("span", { class: `${base}__error` }, error) : null;
723
+ /** Class string for the form control, with the --error modifier when applicable. */
724
+ function controlClass(base, hasError, element = 'input') {
725
+ return `${base}__${element}${hasError ? ` ${base}__${element}--error` : ''}`;
638
726
  }
639
- function formatCurrency(amount, currency, locale) {
640
- if (amount === null || amount === undefined || isNaN(amount))
641
- return '';
642
- return new Intl.NumberFormat(locale, {
643
- style: 'currency',
644
- currency,
645
- minimumFractionDigits: 2,
646
- maximumFractionDigits: 2,
647
- }).format(amount);
648
- }
649
- function formatPercentage(value, locale, decimalPrecision = 2) {
650
- if (value === null || value === undefined || isNaN(value))
651
- return '';
652
- return new Intl.NumberFormat(locale, {
653
- style: 'percent',
654
- minimumFractionDigits: decimalPrecision,
655
- maximumFractionDigits: decimalPrecision,
656
- }).format(value);
657
- }
658
- function formatDate(value, locale) {
659
- if (!value)
660
- return '';
661
- const date = typeof value === 'string' ? new Date(value) : value;
662
- if (isNaN(date.getTime()))
663
- return '';
664
- return new Intl.DateTimeFormat(locale, { year: 'numeric', month: '2-digit', day: '2-digit' }).format(date);
665
- }
666
- function formatDateTime(value, locale) {
667
- if (!value)
668
- return '';
669
- const date = typeof value === 'string' ? new Date(value) : value;
670
- if (isNaN(date.getTime()))
671
- return '';
672
- return new Intl.DateTimeFormat(locale, {
673
- year: 'numeric',
674
- month: '2-digit',
675
- day: '2-digit',
676
- hour: '2-digit',
677
- minute: '2-digit',
678
- }).format(date);
679
- }
680
- function formatTime(value, locale) {
681
- if (!value)
682
- return '';
683
- // value is HH:MM or HH:MM:SS
684
- const [hours, minutes] = value.split(':').map(Number);
685
- const date = new Date();
686
- date.setHours(hours, minutes, 0, 0);
687
- return new Intl.DateTimeFormat(locale, { hour: '2-digit', minute: '2-digit' }).format(date);
688
- }
689
- function parseLocalizedNumber(str, locale) {
690
- var _a, _b, _c, _d;
691
- if (!str || !str.trim())
692
- return null;
693
- // Detect decimal and thousands separators from the locale
694
- const parts = new Intl.NumberFormat(locale).formatToParts(1234567.89);
695
- const groupSep = (_b = (_a = parts.find((p) => p.type === 'group')) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : ',';
696
- const decimalSep = (_d = (_c = parts.find((p) => p.type === 'decimal')) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : '.';
697
- // Remove group separators, replace decimal separator with '.'
698
- const normalized = str
699
- .replace(new RegExp(`\\${groupSep}`, 'g'), '')
700
- .replace(new RegExp(`\\${decimalSep}`), '.')
701
- .replace('%', '')
702
- .trim();
703
- const parsed = parseFloat(normalized);
704
- return isNaN(parsed) ? null : parsed;
727
+ /** Returns the localised required-error, or '' when the value passes. */
728
+ function requiredError(value, required, locale) {
729
+ return required && !validateRequired(value) ? t('required', locale) : '';
705
730
  }
706
731
 
707
- const mrdCurrencyFieldScss = () => `.sc-mrd-currency-field-h{display:block}.mrd-currency-field.sc-mrd-currency-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-currency-field__label.sc-mrd-currency-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-currency-field__label--required.sc-mrd-currency-field::after{content:' *';color:var(--mrd-color-danger)}.mrd-currency-field__row.sc-mrd-currency-field{display:flex;gap:var(--mrd-space-2);align-items:stretch}.mrd-currency-field__amount.sc-mrd-currency-field{flex:1;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;text-align:right;box-sizing:border-box}.mrd-currency-field__amount.sc-mrd-currency-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-currency-field__amount.sc-mrd-currency-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-currency-field__amount--error.sc-mrd-currency-field{border-color:var(--mrd-border-color-error)}.mrd-currency-field__amount--error.sc-mrd-currency-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-currency-field__currency.sc-mrd-currency-field{width:90px;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-space-2);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-medium);color:var(--mrd-input-color);background-color:var(--mrd-color-neutral-50);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);outline:none;cursor:pointer;box-sizing:border-box;appearance:none;text-align:center}.mrd-currency-field__currency.sc-mrd-currency-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-currency-field__currency.sc-mrd-currency-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-currency-field__error.sc-mrd-currency-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}`;
732
+ const mrdCurrencyFieldCss = () => `.sc-mrd-currency-field-h{display:block}.mrd-currency-field.sc-mrd-currency-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-currency-field__label.sc-mrd-currency-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-currency-field__label--required.sc-mrd-currency-field::after{content:" *";color:var(--mrd-color-danger)}.mrd-currency-field__row.sc-mrd-currency-field{display:flex;gap:var(--mrd-space-2);align-items:stretch}.mrd-currency-field__amount.sc-mrd-currency-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box}.mrd-currency-field__amount.sc-mrd-currency-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-currency-field__amount.sc-mrd-currency-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-currency-field__amount.sc-mrd-currency-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-currency-field__amount--error.sc-mrd-currency-field{border-color:var(--mrd-border-color-error)}.mrd-currency-field__amount--error.sc-mrd-currency-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-currency-field__amount.sc-mrd-currency-field{flex:1;text-align:right}.mrd-currency-field__currency.sc-mrd-currency-field{width:90px;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-space-2);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-medium);color:var(--mrd-input-color);background-color:var(--mrd-color-neutral-50);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);outline:none;cursor:pointer;box-sizing:border-box;appearance:none;text-align:center}.mrd-currency-field__currency.sc-mrd-currency-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-currency-field__currency.sc-mrd-currency-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-currency-field__error.sc-mrd-currency-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}`;
708
733
 
709
734
  const COMMON_CURRENCIES = [
710
735
  'EUR', 'USD', 'GBP', 'CHF', 'JPY', 'CNY', 'AUD', 'CAD',
@@ -731,12 +756,7 @@ const MrdCurrencyField = class {
731
756
  this.handleAmountBlur = (e) => {
732
757
  const raw = e.target.value;
733
758
  const parsed = parseLocalizedNumber(raw, this.locale);
734
- if (this.required && !validateRequired(raw)) {
735
- this.error = t('required', this.locale);
736
- }
737
- else {
738
- this.error = '';
739
- }
759
+ this.error = requiredError(raw, this.required, this.locale);
740
760
  const val = { amount: parsed, currency: this.currency };
741
761
  this.mrdChange.emit({ name: this.name, value: val });
742
762
  this.mrdBlur.emit({ name: this.name, value: val });
@@ -755,12 +775,12 @@ const MrdCurrencyField = class {
755
775
  }
756
776
  render() {
757
777
  const hasError = !!this.error;
758
- return (index.h(index.Host, { key: 'fe3520c44d831caf36b388cb5968a9518b16cb8b' }, index.h("div", { key: '50c1fd2d53038e46da575d3e46e1ec26c2da423b', class: "mrd-currency-field" }, this.label && (index.h("label", { key: 'a2649d41bf6e3765c8a62ba6559c64c41615027a', class: `mrd-currency-field__label${this.required ? ' mrd-currency-field__label--required' : ''}` }, this.label)), index.h("div", { key: '952b51f315b4a5c05a8373ce3a3f1041086ba8b8', class: "mrd-currency-field__row" }, index.h("input", { key: '137a72ffc5d79fc8e0a8cf44c012d84a50c26d5b', class: `mrd-currency-field__amount${hasError ? ' mrd-currency-field__amount--error' : ''}`, type: "text", inputMode: "decimal", name: `${this.name}_amount`, value: this.amountDisplay, placeholder: "0.00", required: this.required, disabled: this.disabled, onInput: this.handleAmountInput, onBlur: this.handleAmountBlur }), index.h("select", { key: '1755854ca9b76dc4b41ad84b6b788685931ace36', class: "mrd-currency-field__currency", disabled: this.disabled, onChange: this.handleCurrencyChange }, COMMON_CURRENCIES.map(c => (index.h("option", { key: c, value: c, selected: c === this.currency }, c))))), hasError && index.h("span", { key: '0f10eb98c2e6444651d79d1de92acd0dbcc7133b', class: "mrd-currency-field__error" }, this.error))));
778
+ return (index.h(index.Host, { key: '24c530db6e0420af39fa0a35b31e966286f2d00c' }, index.h("div", { key: '795bc336425fbf1b86828f4a8f5df93930169a3c', class: "mrd-currency-field" }, index.h(FieldLabel, { key: 'b302cd9296c29ed5719b1f768bd5d4eea86f6406', base: "mrd-currency-field", label: this.label, required: this.required }), index.h("div", { key: '7efca51615f405ffd660e120accae32f55a9b5a0', class: "mrd-currency-field__row" }, index.h("input", { key: '5c6fd3549d5631fba49a8a701e6c3a1d0a672890', class: controlClass('mrd-currency-field', hasError, 'amount'), type: "text", inputMode: "decimal", name: `${this.name}_amount`, value: this.amountDisplay, placeholder: "0.00", required: this.required, disabled: this.disabled, onInput: this.handleAmountInput, onBlur: this.handleAmountBlur }), index.h("select", { key: '83ad5e92b623c3c60d161b8828e780adb476682c', class: "mrd-currency-field__currency", disabled: this.disabled, onChange: this.handleCurrencyChange }, COMMON_CURRENCIES.map(c => (index.h("option", { key: c, value: c, selected: c === this.currency }, c))))), index.h(FieldError, { key: 'b059290bb566b119c4f192e750b3e365446243e6', base: "mrd-currency-field", error: this.error }))));
759
779
  }
760
780
  };
761
- MrdCurrencyField.style = mrdCurrencyFieldScss();
781
+ MrdCurrencyField.style = mrdCurrencyFieldCss();
762
782
 
763
- const mrdDateFieldScss = () => `.sc-mrd-date-field-h{display:block}.mrd-date-field.sc-mrd-date-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-date-field__label.sc-mrd-date-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-date-field__label--required.sc-mrd-date-field::after{content:' *';color:var(--mrd-color-danger)}.mrd-date-field__input.sc-mrd-date-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box;cursor:pointer}.mrd-date-field__input.sc-mrd-date-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-date-field__input.sc-mrd-date-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-date-field__input--error.sc-mrd-date-field{border-color:var(--mrd-border-color-error)}.mrd-date-field__input--error.sc-mrd-date-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-date-field__error.sc-mrd-date-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}`;
783
+ const mrdDateFieldCss = () => `.sc-mrd-date-field-h{display:block}.mrd-date-field.sc-mrd-date-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-date-field__label.sc-mrd-date-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-date-field__label--required.sc-mrd-date-field::after{content:" *";color:var(--mrd-color-danger)}.mrd-date-field__input.sc-mrd-date-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box}.mrd-date-field__input.sc-mrd-date-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-date-field__input.sc-mrd-date-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-date-field__input.sc-mrd-date-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-date-field__input--error.sc-mrd-date-field{border-color:var(--mrd-border-color-error)}.mrd-date-field__input--error.sc-mrd-date-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-date-field__error.sc-mrd-date-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}.mrd-date-field__input.sc-mrd-date-field{cursor:pointer}`;
764
784
 
765
785
  const MrdDateField = class {
766
786
  constructor(hostRef) {
@@ -776,12 +796,7 @@ const MrdDateField = class {
776
796
  this.error = '';
777
797
  this.handleChange = (e) => {
778
798
  const val = e.target.value;
779
- if (this.required && !validateRequired(val)) {
780
- this.error = t('required', this.locale);
781
- }
782
- else {
783
- this.error = '';
784
- }
799
+ this.error = requiredError(val, this.required, this.locale);
785
800
  this.mrdChange.emit({ name: this.name, value: val });
786
801
  };
787
802
  this.handleBlur = (e) => {
@@ -790,13 +805,12 @@ const MrdDateField = class {
790
805
  };
791
806
  }
792
807
  render() {
793
- const hasError = !!this.error;
794
- return (index.h(index.Host, { key: '2c0dc2311068a5c759fe8efe58a98a71a9cf4b7b' }, index.h("div", { key: 'ee1cc0e9a2943cc42439825b8f21cd3492eaca05', class: "mrd-date-field" }, this.label && (index.h("label", { key: '3f836a991e676b6070a8b3800edfce00cc0d3b3d', class: `mrd-date-field__label${this.required ? ' mrd-date-field__label--required' : ''}` }, this.label)), index.h("input", { key: '575185661987eea3dc91950f51995b2cc75debea', class: `mrd-date-field__input${hasError ? ' mrd-date-field__input--error' : ''}`, type: "date", name: this.name, value: this.value, required: this.required, disabled: this.disabled, onChange: this.handleChange, onBlur: this.handleBlur }), hasError && index.h("span", { key: '480ec99200989f3dc543d9afc648d83d31992b3c', class: "mrd-date-field__error" }, this.error))));
808
+ return (index.h(index.Host, { key: '71be9e4bcc87b40cf3b777d3fe0bff23c1a0fa94' }, index.h("div", { key: '40ced03df5d4185264ba9d03c832b3870ce8ae19', class: "mrd-date-field" }, index.h(FieldLabel, { key: 'd85ec7c4617a22c8c5862253e8090c85484f8c41', base: "mrd-date-field", label: this.label, required: this.required }), index.h("input", { key: 'c9211fdefdd9527c7ff40ed9de33153303fc1742', class: controlClass('mrd-date-field', !!this.error), type: "date", name: this.name, value: this.value, required: this.required, disabled: this.disabled, onChange: this.handleChange, onBlur: this.handleBlur }), index.h(FieldError, { key: '9dd64475bf8a77bea5344faa71f20485b34b86f9', base: "mrd-date-field", error: this.error }))));
795
809
  }
796
810
  };
797
- MrdDateField.style = mrdDateFieldScss();
811
+ MrdDateField.style = mrdDateFieldCss();
798
812
 
799
- const mrdDatetimeFieldScss = () => `.sc-mrd-datetime-field-h{display:block}.mrd-datetime-field.sc-mrd-datetime-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-datetime-field__label.sc-mrd-datetime-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-datetime-field__label--required.sc-mrd-datetime-field::after{content:' *';color:var(--mrd-color-danger)}.mrd-datetime-field__input.sc-mrd-datetime-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box;cursor:pointer}.mrd-datetime-field__input.sc-mrd-datetime-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-datetime-field__input.sc-mrd-datetime-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-datetime-field__input--error.sc-mrd-datetime-field{border-color:var(--mrd-border-color-error)}.mrd-datetime-field__input--error.sc-mrd-datetime-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-datetime-field__error.sc-mrd-datetime-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}`;
813
+ const mrdDatetimeFieldCss = () => `.sc-mrd-datetime-field-h{display:block}.mrd-datetime-field.sc-mrd-datetime-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-datetime-field__label.sc-mrd-datetime-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-datetime-field__label--required.sc-mrd-datetime-field::after{content:" *";color:var(--mrd-color-danger)}.mrd-datetime-field__input.sc-mrd-datetime-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box}.mrd-datetime-field__input.sc-mrd-datetime-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-datetime-field__input.sc-mrd-datetime-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-datetime-field__input.sc-mrd-datetime-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-datetime-field__input--error.sc-mrd-datetime-field{border-color:var(--mrd-border-color-error)}.mrd-datetime-field__input--error.sc-mrd-datetime-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-datetime-field__error.sc-mrd-datetime-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}.mrd-datetime-field__input.sc-mrd-datetime-field{cursor:pointer}`;
800
814
 
801
815
  const MrdDatetimeField = class {
802
816
  constructor(hostRef) {
@@ -814,12 +828,7 @@ const MrdDatetimeField = class {
814
828
  this.handleChange = (e) => {
815
829
  const localVal = e.target.value;
816
830
  this.localValue = localVal;
817
- if (this.required && !validateRequired(localVal)) {
818
- this.error = t('required', this.locale);
819
- }
820
- else {
821
- this.error = '';
822
- }
831
+ this.error = requiredError(localVal, this.required, this.locale);
823
832
  this.mrdChange.emit({ name: this.name, value: this.localToUtc(localVal) });
824
833
  };
825
834
  this.handleBlur = (e) => {
@@ -853,8 +862,7 @@ const MrdDatetimeField = class {
853
862
  return d.toISOString().replace(/\.\d{3}Z$/, 'Z');
854
863
  }
855
864
  render() {
856
- const hasError = !!this.error;
857
- return (index.h(index.Host, { key: 'ea8b3b68100ffdb316bc5048f82d85d238bb2e4b' }, index.h("div", { key: 'c192c6998ee474aaf4df7b3b97ae0bd61f6d624d', class: "mrd-datetime-field" }, this.label && (index.h("label", { key: '1fbd66c17d76508f0d698a2c258be6779e98d85e', class: `mrd-datetime-field__label${this.required ? ' mrd-datetime-field__label--required' : ''}` }, this.label)), index.h("input", { key: 'fc9612c062a1cab5076a06598cabf227adce996c', class: `mrd-datetime-field__input${hasError ? ' mrd-datetime-field__input--error' : ''}`, type: "datetime-local", name: this.name, value: this.localValue, required: this.required, disabled: this.disabled, onChange: this.handleChange, onBlur: this.handleBlur }), hasError && index.h("span", { key: '8788ac01739302f6ad61010b238ff38d45e1b68a', class: "mrd-datetime-field__error" }, this.error))));
865
+ return (index.h(index.Host, { key: 'ac07ec2ba79cde998d1247e9d71de336c0e72a64' }, index.h("div", { key: '8144cf68c4b6b9cbc8396903b84bb355f380ceda', class: "mrd-datetime-field" }, index.h(FieldLabel, { key: '972686469f68c932e33b8d2c3806422553a3cce3', base: "mrd-datetime-field", label: this.label, required: this.required }), index.h("input", { key: '370b6032c38fbee22e662c1b2871f96b53b58956', class: controlClass('mrd-datetime-field', !!this.error), type: "datetime-local", name: this.name, value: this.localValue, required: this.required, disabled: this.disabled, onChange: this.handleChange, onBlur: this.handleBlur }), index.h(FieldError, { key: 'b7a812f82a6b0d2c938aa1f1c2494df685258555', base: "mrd-datetime-field", error: this.error }))));
858
866
  }
859
867
  static get watchers() { return {
860
868
  "value": [{
@@ -862,9 +870,9 @@ const MrdDatetimeField = class {
862
870
  }]
863
871
  }; }
864
872
  };
865
- MrdDatetimeField.style = mrdDatetimeFieldScss();
873
+ MrdDatetimeField.style = mrdDatetimeFieldCss();
866
874
 
867
- const mrdDocumentContainerScss = () => `.sc-mrd-document-container-h{display:block}.mrd-document-container__toolbar.sc-mrd-document-container{display:flex;align-items:center;justify-content:flex-end;gap:var(--mrd-space-2);padding:var(--mrd-space-2) var(--mrd-space-4);border-bottom:1px solid var(--mrd-color-neutral-100)}.mrd-document-container__action.sc-mrd-document-container{display:inline-flex;align-items:center;gap:var(--mrd-space-2);height:1.625rem;padding:0 var(--mrd-space-3);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-700);background:var(--mrd-color-white);border:1px solid var(--mrd-color-neutral-200);border-radius:var(--mrd-border-radius);cursor:pointer;transition:background var(--mrd-transition-fast), border-color var(--mrd-transition-fast)}.mrd-document-container__action.sc-mrd-document-container svg.sc-mrd-document-container{width:1rem;height:1rem;color:#d9a441}.mrd-document-container__action.sc-mrd-document-container:hover:not(:disabled){background:var(--mrd-color-neutral-50);border-color:var(--mrd-color-neutral-300)}.mrd-document-container__action.sc-mrd-document-container:disabled{opacity:0.5;cursor:not-allowed}.mrd-document-container__seg.sc-mrd-document-container{display:inline-flex;gap:2px;padding:2px;background:var(--mrd-color-neutral-100);border-radius:var(--mrd-border-radius)}.mrd-document-container__seg-btn.sc-mrd-document-container{width:1.875rem;height:1.625rem;display:grid;place-items:center;border:none;background:none;border-radius:var(--mrd-border-radius-sm);color:var(--mrd-color-neutral-500);cursor:pointer;transition:color var(--mrd-transition-fast), background var(--mrd-transition-fast)}.mrd-document-container__seg-btn.sc-mrd-document-container:hover{color:var(--mrd-color-neutral-800)}.mrd-document-container__seg-btn[aria-pressed='true'].sc-mrd-document-container{background:var(--mrd-color-white);color:var(--mrd-color-primary-dark);box-shadow:var(--mrd-shadow-sm)}.mrd-document-container__seg-btn.sc-mrd-document-container svg.sc-mrd-document-container{width:1rem;height:1rem}`;
875
+ const mrdDocumentContainerCss = () => `.sc-mrd-document-container-h{display:block}.mrd-document-container__toolbar.sc-mrd-document-container{display:flex;align-items:center;justify-content:flex-end;gap:var(--mrd-space-2);padding:var(--mrd-space-2) var(--mrd-space-4);border-bottom:1px solid var(--mrd-color-neutral-100)}.mrd-document-container__action.sc-mrd-document-container{display:inline-flex;align-items:center;gap:var(--mrd-space-2);height:1.625rem;padding:0 var(--mrd-space-3);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-700);background:var(--mrd-color-white);border:1px solid var(--mrd-color-neutral-200);border-radius:var(--mrd-border-radius);cursor:pointer;transition:background var(--mrd-transition-fast), border-color var(--mrd-transition-fast)}.mrd-document-container__action.sc-mrd-document-container svg.sc-mrd-document-container{width:1rem;height:1rem;color:var(--mrd-color-folder)}.mrd-document-container__action.sc-mrd-document-container:hover:not(:disabled){background:var(--mrd-color-neutral-50);border-color:var(--mrd-color-neutral-300)}.mrd-document-container__action.sc-mrd-document-container:disabled{opacity:0.5;cursor:not-allowed}.mrd-document-container__seg.sc-mrd-document-container{display:inline-flex;gap:2px;padding:2px;background:var(--mrd-color-neutral-100);border-radius:var(--mrd-border-radius)}.mrd-document-container__seg-btn.sc-mrd-document-container{width:1.875rem;height:1.625rem;display:grid;place-items:center;border:none;background:none;border-radius:var(--mrd-border-radius-sm);color:var(--mrd-color-neutral-500);cursor:pointer;transition:color var(--mrd-transition-fast), background var(--mrd-transition-fast)}.mrd-document-container__seg-btn.sc-mrd-document-container:hover{color:var(--mrd-color-neutral-800)}.mrd-document-container__seg-btn[aria-pressed=true].sc-mrd-document-container{background:var(--mrd-color-white);color:var(--mrd-color-primary-dark);box-shadow:var(--mrd-shadow-sm)}.mrd-document-container__seg-btn.sc-mrd-document-container svg.sc-mrd-document-container{width:1rem;height:1rem}`;
868
876
 
869
877
  const MrdDocumentContainer = class {
870
878
  constructor(hostRef) {
@@ -881,8 +889,13 @@ const MrdDocumentContainer = class {
881
889
  this.item = null;
882
890
  /** Parent record id — required for RELATED_VIEW path building. */
883
891
  this.parentId = '';
892
+ /** Canonical parent href, forwarded to the folder tree for single-container seeding. */
893
+ this.containerHref = '';
884
894
  /** Lookup key used for the embedded `data-doclist` / `data-view` attributes. */
885
895
  this.viewKey = '';
896
+ /** Fixed height (px) of the scrolling folder-tree body — the toolbar stays put
897
+ * on top, Finder-style. The table manages its own height. */
898
+ this.height = 460;
886
899
  this.locale = navigator.language;
887
900
  /** Active body: folder tree or flat table. */
888
901
  this.mode = 'tree';
@@ -891,8 +904,8 @@ const MrdDocumentContainer = class {
891
904
  /** Whether the currently mounted table has been init()'d. Reset on every mode switch. */
892
905
  this.tableInited = false;
893
906
  this.createFolder = () => {
894
- var _a, _b;
895
- (_b = (_a = this.listEl) === null || _a === void 0 ? void 0 : _a.createFolder) === null || _b === void 0 ? void 0 : _b.call(_a);
907
+ var _a;
908
+ (_a = this.listEl) === null || _a === void 0 ? void 0 : _a.createFolder();
896
909
  };
897
910
  }
898
911
  /** The embedded table does not self-load: like every mrd-table it waits for the
@@ -904,7 +917,7 @@ const MrdDocumentContainer = class {
904
917
  if (this.mode === 'list' && this.tableEl && !this.tableInited) {
905
918
  this.tableInited = true;
906
919
  const table = this.tableEl;
907
- Promise.resolve((_a = table.componentOnReady) === null || _a === void 0 ? void 0 : _a.call(table)).then(() => { var _a; return (_a = table.init) === null || _a === void 0 ? void 0 : _a.call(table); });
920
+ Promise.resolve((_a = table.componentOnReady) === null || _a === void 0 ? void 0 : _a.call(table)).then(() => table.init());
908
921
  }
909
922
  }
910
923
  setMode(mode) {
@@ -922,7 +935,7 @@ const MrdDocumentContainer = class {
922
935
  }
923
936
  // ── Bodies ───────────────────────────────────────────────────────────────
924
937
  renderTree() {
925
- return (index.h("mrd-document-list", { "data-doclist": this.viewKey, ref: el => (this.listEl = el), item: this.item, archetype: this.archetype, parentId: this.parentId, locale: this.locale, onMrdLoadDistinct: (e) => {
938
+ return (index.h("mrd-document-list", { "data-doclist": this.viewKey, ref: el => (this.listEl = el), item: this.item, archetype: this.archetype, parentId: this.parentId, containerHref: this.containerHref, locale: this.locale, onMrdLoadDistinct: (e) => {
926
939
  e.stopPropagation();
927
940
  this.mrdLoadDistinct.emit(e.detail);
928
941
  }, onMrdLoadPage: (e) => {
@@ -963,13 +976,241 @@ const MrdDocumentContainer = class {
963
976
  } }));
964
977
  }
965
978
  render() {
966
- return (index.h(index.Host, { key: 'a5393d484bdc202b57c6d32d9ce917e760aff95a' }, this.renderToolbar(), index.h("div", { key: '52f82de8f7734e13f34d323e3e831e6de5676f46', class: "mrd-document-container__body" }, this.mode === 'tree' ? this.renderTree() : this.renderList())));
979
+ const treeMode = this.mode === 'tree';
980
+ return (index.h(index.Host, { key: '018c9eacd169fdf7d352a51472651348af2b45df' }, this.renderToolbar(), index.h("div", { key: '5ff2ac77d4d12369905696ff075f99785dc1c809', class: "mrd-document-container__body", style: treeMode ? { height: `${this.height}px`, overflowY: 'auto' } : {} }, treeMode ? this.renderTree() : this.renderList())));
967
981
  }
968
982
  get el() { return index.getElement(this); }
969
983
  };
970
- MrdDocumentContainer.style = mrdDocumentContainerScss();
984
+ MrdDocumentContainer.style = mrdDocumentContainerCss();
985
+
986
+ /**
987
+ * Shared path/query-param conventions for list requests,
988
+ * used by mrd-table and mrd-document-list.
989
+ */
990
+ /** Applies the view-level static filters to `params` using the API operator conventions. */
991
+ function applyViewFilters(params, filters) {
992
+ var _a, _b, _c;
993
+ for (const f of filters !== null && filters !== void 0 ? filters : []) {
994
+ if (!f.name)
995
+ continue;
996
+ if (f.operator === 'EMPTY') {
997
+ params.set(f.name, '');
998
+ continue;
999
+ }
1000
+ if (f.operator === 'NOT_EMPTY') {
1001
+ params.set(f.name + '_notempty', 'true');
1002
+ continue;
1003
+ }
1004
+ if (f.operator === 'STARTS_WITH') {
1005
+ params.set(f.name + '_startswith', String((_a = f.value) !== null && _a !== void 0 ? _a : ''));
1006
+ continue;
1007
+ }
1008
+ if (f.operator === 'FROM') {
1009
+ params.set(f.name + '_from', String((_b = f.value) !== null && _b !== void 0 ? _b : ''));
1010
+ continue;
1011
+ }
1012
+ if (f.operator === 'TO') {
1013
+ params.set(f.name + '_to', String((_c = f.value) !== null && _c !== void 0 ? _c : ''));
1014
+ continue;
1015
+ }
1016
+ if (f.value != null) {
1017
+ params.set(f.name, String(f.value));
1018
+ }
1019
+ }
1020
+ }
1021
+ /** VIEW: `/{dataClass}`; RELATED_VIEW: `/{fromClass}/{parentId}/{dataClass}`. */
1022
+ function buildListPath(opts) {
1023
+ var _a, _b, _c;
1024
+ if (opts.isRelatedView) {
1025
+ return `/${(_a = opts.fromClass) !== null && _a !== void 0 ? _a : ''}/${opts.parentId}/${(_b = opts.dataClass) !== null && _b !== void 0 ? _b : ''}`;
1026
+ }
1027
+ return `/${(_c = opts.dataClass) !== null && _c !== void 0 ? _c : ''}`;
1028
+ }
1029
+
1030
+ /**
1031
+ * Tree model and pure tree logic for mrd-document-list.
1032
+ * Nodes are mutated in place; the component triggers re-renders via bump().
1033
+ */
1034
+ /** Normalise a folder path: null/""/"/" → root ([]); else split on "/" dropping empties. */
1035
+ function splitFolder(path) {
1036
+ if (path == null)
1037
+ return [];
1038
+ const s = String(path).trim();
1039
+ if (s === '' || s === '/')
1040
+ return [];
1041
+ return s.split('/').map(x => x.trim()).filter(Boolean);
1042
+ }
1043
+ function makeContainerNode(href, label, count) {
1044
+ return {
1045
+ id: 'c:' + href, kind: 'container', label, href,
1046
+ hasDocs: false, docCount: 0, totalCount: count, children: [],
1047
+ open: false, loading: false, foldersLoaded: false, docsLoaded: false, docs: [],
1048
+ };
1049
+ }
1050
+ function makeFolderNode(id, label, containerId) {
1051
+ return {
1052
+ id, kind: 'folder', label, containerId,
1053
+ hasDocs: false, docCount: 0, totalCount: 0, children: [],
1054
+ open: false, loading: false, foldersLoaded: false, docsLoaded: false, docs: [],
1055
+ };
1056
+ }
1057
+ /** Recompute totalCount over the subtree; returns the node's aggregate. */
1058
+ function computeTotals(node) {
1059
+ let total = node.docCount;
1060
+ for (const c of node.children)
1061
+ total += computeTotals(c);
1062
+ node.totalCount = total;
1063
+ return total;
1064
+ }
1065
+ /** Folder path segments of a node relative to its container (derived from its id). */
1066
+ function segmentsOf(node, container) {
1067
+ if (node.kind === 'container')
1068
+ return [];
1069
+ const prefix = container.id + '/';
1070
+ const rest = node.id.startsWith(prefix) ? node.id.slice(prefix.length) : '';
1071
+ return rest ? rest.split('/') : [];
1072
+ }
1073
+ /** Folder string a node represents: the raw distinct value when it holds
1074
+ * documents, else derived from its path segments; null for a container root. */
1075
+ function folderStringOf(node, container) {
1076
+ if (node.kind === 'container')
1077
+ return null;
1078
+ if (node.fullPath != null && node.fullPath !== '')
1079
+ return node.fullPath;
1080
+ const segs = segmentsOf(node, container);
1081
+ return segs.length ? '/' + segs.join('/') : null;
1082
+ }
1083
+ /** Strip a single trailing extension for the document title. */
1084
+ function stripExtension(name) {
1085
+ return name.replace(/\.[^./\\]+$/, '');
1086
+ }
1087
+ /** Rebuild a container's folder subtree from the /distinct folder strings.
1088
+ * New nodes are registered in `nodeIndex`; the container is mutated in place. */
1089
+ function applyFolderDistinct(container, values, nodeIndex) {
1090
+ container.children = [];
1091
+ container.hasDocs = false;
1092
+ container.docCount = 0;
1093
+ for (const v of values) {
1094
+ const raw = typeof v.value === 'string' ? v.value : v.value == null ? '' : String(v.value);
1095
+ const segs = splitFolder(raw);
1096
+ if (segs.length === 0) {
1097
+ // Root documents — the container's own direct documents.
1098
+ container.hasDocs = true;
1099
+ container.docCount = v.count;
1100
+ container.fullPath = raw;
1101
+ continue;
1102
+ }
1103
+ let node = container;
1104
+ const acc = [];
1105
+ for (const seg of segs) {
1106
+ acc.push(seg);
1107
+ let child = node.children.find(c => c.label === seg);
1108
+ if (!child) {
1109
+ child = makeFolderNode(container.id + '/' + acc.join('/'), seg, container.id);
1110
+ node.children.push(child);
1111
+ nodeIndex.set(child.id, child);
1112
+ }
1113
+ node = child;
1114
+ }
1115
+ node.hasDocs = true;
1116
+ node.docCount = v.count;
1117
+ node.fullPath = raw;
1118
+ }
1119
+ computeTotals(container);
1120
+ container.foldersLoaded = true;
1121
+ container.loading = false;
1122
+ }
1123
+ /** Optimistic in-place tree update for a document moved between folders. */
1124
+ function applyDocMove(doc, fromNode, toNode, targetFolder) {
1125
+ fromNode.docs = fromNode.docs.filter(d => d !== doc);
1126
+ fromNode.docCount = Math.max(0, fromNode.docCount - 1);
1127
+ // A now-empty folder should stop showing an expand chevron (it disappears on
1128
+ // the next reload anyway, since it is derived from document folder strings).
1129
+ if (fromNode.docsLoaded)
1130
+ fromNode.hasDocs = fromNode.docs.length > 0;
1131
+ toNode.hasDocs = true;
1132
+ toNode.pending = false; // a pending folder is now materialised
1133
+ toNode.docCount += 1;
1134
+ if (toNode.kind === 'folder')
1135
+ toNode.fullPath = targetFolder !== null && targetFolder !== void 0 ? targetFolder : '';
1136
+ if (toNode.docsLoaded)
1137
+ toNode.docs = [...toNode.docs, doc];
1138
+ }
971
1139
 
972
- const mrdDocumentListScss = () => `.sc-mrd-document-list-h{display:block}.mrd-document-list.sc-mrd-document-list{padding:var(--mrd-space-2) 0}.mrd-document-list__row.sc-mrd-document-list{display:flex;align-items:center;gap:var(--mrd-space-2);height:2.125rem;padding:0 var(--mrd-space-4);cursor:pointer;user-select:none;font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-800)}.mrd-document-list__row.sc-mrd-document-list:hover{background:var(--mrd-color-neutral-50)}.mrd-document-list__row--selected.sc-mrd-document-list{background:var(--mrd-color-primary-50, rgba(22, 163, 74, 0.1))}.mrd-document-list__row--selected.sc-mrd-document-list:hover{background:var(--mrd-color-primary-50, rgba(22, 163, 74, 0.1))}.mrd-document-list__row--pending.sc-mrd-document-list .mrd-document-list__label.sc-mrd-document-list{font-style:italic;color:var(--mrd-color-neutral-500)}.mrd-document-list__row--doc.sc-mrd-document-list{cursor:grab}.mrd-document-list__row--doc.sc-mrd-document-list:active{cursor:grabbing}.mrd-document-list__row--drop.sc-mrd-document-list{background:var(--mrd-color-primary-50, rgba(22, 163, 74, 0.1));box-shadow:inset 0 0 0 1px var(--mrd-color-primary)}.mrd-document-list__row--drop.sc-mrd-document-list:hover{background:var(--mrd-color-primary-50, rgba(22, 163, 74, 0.1))}.mrd-document-list__row--edit.sc-mrd-document-list{cursor:default}.mrd-document-list__name-input.sc-mrd-document-list{flex:1;min-width:0;height:1.625rem;padding:0 var(--mrd-space-2);font-size:var(--mrd-font-size-sm);font-family:inherit;color:var(--mrd-color-neutral-800);border:1px solid var(--mrd-color-primary);border-radius:var(--mrd-border-radius);outline:none;box-shadow:var(--mrd-shadow-focus)}.mrd-document-list__error.sc-mrd-document-list{font-size:var(--mrd-font-size-xs);color:var(--mrd-color-danger, #dc2626);padding-top:0.125rem;padding-bottom:0.25rem}.mrd-document-list__row--dossier.sc-mrd-document-list .mrd-document-list__label.sc-mrd-document-list{font-weight:var(--mrd-font-weight-semibold)}.mrd-document-list__indent.sc-mrd-document-list{flex:none}.mrd-document-list__chev.sc-mrd-document-list{width:1rem;height:1rem;flex:none;display:grid;place-items:center;color:var(--mrd-color-neutral-400);transition:transform var(--mrd-transition-fast)}.mrd-document-list__chev.sc-mrd-document-list svg.sc-mrd-document-list{width:0.6875rem;height:0.6875rem}.mrd-document-list__chev--open.sc-mrd-document-list{transform:rotate(90deg)}.mrd-document-list__chev--leaf.sc-mrd-document-list{visibility:hidden}.mrd-document-list__icon.sc-mrd-document-list{width:1.0625rem;height:1.0625rem;flex:none}.mrd-document-list__icon--dossier.sc-mrd-document-list{color:var(--mrd-color-primary)}.mrd-document-list__icon--folder.sc-mrd-document-list{color:#d9a441}.mrd-document-list__icon--doc.sc-mrd-document-list{color:var(--mrd-color-neutral-400)}.mrd-document-list__label.sc-mrd-document-list{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mrd-document-list__count.sc-mrd-document-list{flex:none;font-family:var(--mrd-font-family-mono);font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-500);background:var(--mrd-color-neutral-100);border-radius:var(--mrd-border-radius-full);padding:0.0625rem 0.5rem}.mrd-document-list__date.sc-mrd-document-list{flex:none;font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-400);font-variant-numeric:tabular-nums}.mrd-document-list__loading.sc-mrd-document-list{display:flex;align-items:center;gap:var(--mrd-space-2);height:1.875rem;padding:0 var(--mrd-space-4);font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-400)}.mrd-document-list__spinner.sc-mrd-document-list{width:0.75rem;height:0.75rem;border:2px solid var(--mrd-color-neutral-300);border-top-color:var(--mrd-color-primary);border-radius:50%;animation:mrd-document-list-spin 0.7s linear infinite}@keyframes mrd-document-list-spin{to{transform:rotate(360deg)}}.mrd-document-list__empty.sc-mrd-document-list{padding:var(--mrd-space-8) var(--mrd-space-4);text-align:center;color:var(--mrd-color-neutral-400);font-size:var(--mrd-font-size-sm)}`;
1140
+ function chevron(open, leaf) {
1141
+ return (index.h("span", { class: `mrd-document-list__chev${leaf ? ' mrd-document-list__chev--leaf' : ''}${open ? ' mrd-document-list__chev--open' : ''}` }, index.h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, index.h("path", { d: "M9 6l6 6-6 6" }))));
1142
+ }
1143
+ function dossierIcon() {
1144
+ return (index.h("svg", { class: "mrd-document-list__icon mrd-document-list__icon--dossier", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, index.h("path", { d: "M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" })));
1145
+ }
1146
+ function folderIcon() {
1147
+ return (index.h("svg", { class: "mrd-document-list__icon mrd-document-list__icon--folder", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, index.h("path", { d: "M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" })));
1148
+ }
1149
+ function docIcon() {
1150
+ return (index.h("svg", { class: "mrd-document-list__icon mrd-document-list__icon--doc", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, index.h("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }), index.h("path", { d: "M14 2v6h6" })));
1151
+ }
1152
+ function indent(depth) {
1153
+ return index.h("span", { class: "mrd-document-list__indent", style: { width: `${depth * 18}px` } });
1154
+ }
1155
+ function renderLoadingRow(ctx, depth) {
1156
+ return (index.h("div", { class: "mrd-document-list__loading", key: "loading" }, indent(depth), index.h("span", { class: "mrd-document-list__spinner" }), t('loading', ctx.locale)));
1157
+ }
1158
+ function renderUploadingRow(ctx, depth) {
1159
+ return (index.h("div", { class: "mrd-document-list__loading", key: "uploading" }, indent(depth), index.h("span", { class: "mrd-document-list__spinner" }), t('upload_file', ctx.locale)));
1160
+ }
1161
+ function renderDocRow(ctx, doc, node, container, depth) {
1162
+ var _a, _b, _c, _d, _e;
1163
+ const label = (_b = (_a = doc === null || doc === void 0 ? void 0 : doc[ctx.titleField]) !== null && _a !== void 0 ? _a : doc === null || doc === void 0 ? void 0 : doc.name) !== null && _b !== void 0 ? _b : '';
1164
+ const dateRaw = ctx.dateField ? doc === null || doc === void 0 ? void 0 : doc[ctx.dateField] : undefined;
1165
+ const date = dateRaw ? formatDate(dateRaw, ctx.locale) : '';
1166
+ return (index.h("div", { class: "mrd-document-list__row mrd-document-list__row--doc", key: (_e = (_d = (_c = doc === null || doc === void 0 ? void 0 : doc._links) === null || _c === void 0 ? void 0 : _c.self) === null || _d === void 0 ? void 0 : _d.href) !== null && _e !== void 0 ? _e : label, draggable: true, onClick: () => ctx.on.openDoc(doc), onDragStart: (e) => ctx.on.docDragStart(e, doc, node), onDragEnd: ctx.on.docDragEnd, onDragOver: (e) => ctx.on.nodeDragOver(e, node), onDragLeave: () => ctx.on.nodeDragLeave(node), onDrop: (e) => ctx.on.nodeDrop(e, node, container) }, indent(depth), chevron(false, true), docIcon(), index.h("span", { class: "mrd-document-list__label" }, label), date && index.h("span", { class: "mrd-document-list__date" }, date)));
1167
+ }
1168
+ function renderFolderEditRow(ctx, node, depth) {
1169
+ return (index.h("div", { class: "mrd-document-list__node", key: node.id }, index.h("div", { class: "mrd-document-list__row mrd-document-list__row--edit" }, indent(depth), chevron(false, true), folderIcon(), index.h("input", { class: "mrd-document-list__name-input", type: "text", placeholder: t('folder_name_placeholder', ctx.locale), ref: el => ctx.on.setPendingInputEl(el), onInput: ctx.on.pendingInput, onKeyDown: ctx.on.pendingKeyDown, onBlur: () => ctx.on.cancelFolder() })), node.error && (index.h("div", { class: "mrd-document-list__error", style: { paddingLeft: `${depth * 18 + 52}px` } }, node.error))));
1170
+ }
1171
+ function renderNodeChildren(ctx, container, node, depth) {
1172
+ const out = [];
1173
+ // Direct documents of this node (root docs live on the container node).
1174
+ if (node.hasDocs) {
1175
+ if (node.docsLoaded) {
1176
+ for (const doc of node.docs)
1177
+ out.push(renderDocRow(ctx, doc, node, container, depth));
1178
+ }
1179
+ else if (node.loading) {
1180
+ out.push(renderLoadingRow(ctx, depth));
1181
+ }
1182
+ }
1183
+ // Child folders.
1184
+ for (const child of node.children) {
1185
+ out.push(renderFolderNode(ctx, container, child, depth));
1186
+ }
1187
+ // An uploading file dropped onto this node.
1188
+ if (node.id === ctx.uploadingNodeId)
1189
+ out.push(renderUploadingRow(ctx, depth));
1190
+ return out;
1191
+ }
1192
+ function renderFolderNode(ctx, container, node, depth) {
1193
+ if (node.editing)
1194
+ return renderFolderEditRow(ctx, node, depth);
1195
+ const leaf = node.children.length === 0 && !node.hasDocs;
1196
+ const selected = node.id === ctx.selectedId;
1197
+ const cls = 'mrd-document-list__row'
1198
+ + (selected ? ' mrd-document-list__row--selected' : '')
1199
+ + (node.pending ? ' mrd-document-list__row--pending' : '')
1200
+ + (node.id === ctx.dropTargetId ? ' mrd-document-list__row--drop' : '');
1201
+ return (index.h("div", { class: "mrd-document-list__node", key: node.id }, index.h("div", { class: cls, onClick: () => ctx.on.toggleFolder(container, node), onDragOver: (e) => ctx.on.nodeDragOver(e, node), onDragLeave: () => ctx.on.nodeDragLeave(node), onDrop: (e) => ctx.on.nodeDrop(e, node, container) }, indent(depth), chevron(node.open, leaf), folderIcon(), index.h("span", { class: "mrd-document-list__label" }, node.label), index.h("span", { class: "mrd-document-list__count" }, node.totalCount)), node.open && index.h("div", { class: "mrd-document-list__kids" }, renderNodeChildren(ctx, container, node, depth + 1))));
1202
+ }
1203
+ function renderContainerNode(ctx, node, depth) {
1204
+ const selected = node.id === ctx.selectedId;
1205
+ const cls = 'mrd-document-list__row mrd-document-list__row--dossier'
1206
+ + (selected ? ' mrd-document-list__row--selected' : '')
1207
+ + (node.id === ctx.dropTargetId ? ' mrd-document-list__row--drop' : '');
1208
+ return (index.h("div", { class: "mrd-document-list__node", key: node.id }, index.h("div", { class: cls, onClick: () => ctx.on.toggleContainer(node), onDragOver: (e) => ctx.on.nodeDragOver(e, node), onDragLeave: () => ctx.on.nodeDragLeave(node), onDrop: (e) => ctx.on.nodeDrop(e, node, node) }, indent(depth), chevron(node.open, false), dossierIcon(), index.h("span", { class: "mrd-document-list__label" }, node.label), index.h("span", { class: "mrd-document-list__count" }, node.totalCount)), node.open && (index.h("div", { class: "mrd-document-list__kids" }, node.loading && !node.foldersLoaded
1209
+ ? renderLoadingRow(ctx, depth + 1)
1210
+ : renderNodeChildren(ctx, node, node, depth + 1)))));
1211
+ }
1212
+
1213
+ const mrdDocumentListCss = () => `@charset "UTF-8";.sc-mrd-document-list-h{display:block;height:100%}.mrd-document-list.sc-mrd-document-list{padding:var(--mrd-space-2) 0;min-height:100%;box-sizing:border-box}.mrd-document-list--drop-active.sc-mrd-document-list{outline:2px dashed var(--mrd-color-primary);outline-offset:-4px;background:var(--mrd-color-primary-50, rgba(22, 163, 74, 0.06))}.mrd-document-list__row.sc-mrd-document-list{display:flex;align-items:center;gap:var(--mrd-space-2);height:2.125rem;padding:0 var(--mrd-space-4);cursor:pointer;user-select:none;font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-800)}.mrd-document-list__row.sc-mrd-document-list:hover{background:var(--mrd-color-neutral-50)}.mrd-document-list__row--selected.sc-mrd-document-list{background:var(--mrd-color-primary-50, rgba(22, 163, 74, 0.1))}.mrd-document-list__row--selected.sc-mrd-document-list:hover{background:var(--mrd-color-primary-50, rgba(22, 163, 74, 0.1))}.mrd-document-list__row--pending.sc-mrd-document-list .mrd-document-list__label.sc-mrd-document-list{font-style:italic;color:var(--mrd-color-neutral-500)}.mrd-document-list__row--doc.sc-mrd-document-list{cursor:grab}.mrd-document-list__row--doc.sc-mrd-document-list:active{cursor:grabbing}.mrd-document-list__row--drop.sc-mrd-document-list{background:var(--mrd-color-primary-50, rgba(22, 163, 74, 0.1));box-shadow:inset 0 0 0 1px var(--mrd-color-primary)}.mrd-document-list__row--drop.sc-mrd-document-list:hover{background:var(--mrd-color-primary-50, rgba(22, 163, 74, 0.1))}.mrd-document-list__row--edit.sc-mrd-document-list{cursor:default}.mrd-document-list__name-input.sc-mrd-document-list{flex:1;min-width:0;height:1.625rem;padding:0 var(--mrd-space-2);font-size:var(--mrd-font-size-sm);font-family:inherit;color:var(--mrd-color-neutral-800);border:1px solid var(--mrd-color-primary);border-radius:var(--mrd-border-radius);outline:none;box-shadow:var(--mrd-shadow-focus)}.mrd-document-list__error.sc-mrd-document-list{font-size:var(--mrd-font-size-xs);color:var(--mrd-color-danger, #dc2626);padding-top:0.125rem;padding-bottom:0.25rem}.mrd-document-list__row--dossier.sc-mrd-document-list .mrd-document-list__label.sc-mrd-document-list{font-weight:var(--mrd-font-weight-semibold)}.mrd-document-list__indent.sc-mrd-document-list{flex:none}.mrd-document-list__chev.sc-mrd-document-list{width:1rem;height:1rem;flex:none;display:grid;place-items:center;color:var(--mrd-color-neutral-400);transition:transform var(--mrd-transition-fast)}.mrd-document-list__chev.sc-mrd-document-list svg.sc-mrd-document-list{width:0.6875rem;height:0.6875rem}.mrd-document-list__chev--open.sc-mrd-document-list{transform:rotate(90deg)}.mrd-document-list__chev--leaf.sc-mrd-document-list{visibility:hidden}.mrd-document-list__icon.sc-mrd-document-list{width:1.0625rem;height:1.0625rem;flex:none}.mrd-document-list__icon--dossier.sc-mrd-document-list{color:var(--mrd-color-primary)}.mrd-document-list__icon--folder.sc-mrd-document-list{color:var(--mrd-color-folder)}.mrd-document-list__icon--doc.sc-mrd-document-list{color:var(--mrd-color-neutral-400)}.mrd-document-list__label.sc-mrd-document-list{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mrd-document-list__count.sc-mrd-document-list{flex:none;font-family:var(--mrd-font-family-mono);font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-500);background:var(--mrd-color-neutral-100);border-radius:var(--mrd-border-radius-full);padding:0.0625rem 0.5rem}.mrd-document-list__date.sc-mrd-document-list{flex:none;font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-400);font-variant-numeric:tabular-nums}.mrd-document-list__loading.sc-mrd-document-list{display:flex;align-items:center;gap:var(--mrd-space-2);height:1.875rem;padding:0 var(--mrd-space-4);font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-400)}.mrd-document-list__spinner.sc-mrd-document-list{width:0.75rem;height:0.75rem;border:2px solid var(--mrd-color-neutral-300);border-top-color:var(--mrd-color-primary);border-radius:50%;animation:mrd-document-list-spin 0.7s linear infinite}@keyframes mrd-document-list-spin{to{transform:rotate(360deg)}}.mrd-document-list__empty.sc-mrd-document-list{padding:var(--mrd-space-8) var(--mrd-space-4);text-align:center;color:var(--mrd-color-neutral-400);font-size:var(--mrd-font-size-sm)}`;
973
1214
 
974
1215
  const MrdDocumentList = class {
975
1216
  constructor(hostRef) {
@@ -985,6 +1226,11 @@ const MrdDocumentList = class {
985
1226
  this.item = null;
986
1227
  /** Parent record id — required for RELATED_VIEW path building. */
987
1228
  this.parentId = '';
1229
+ /** Canonical parent href (`/{base}/{tenant}/{fromClass}/{parentId}`) supplied by
1230
+ * the host. When the RELATED_VIEW's `inverseRelation` equals the archetype
1231
+ * `container` slot, this seeds a single container so an empty dossier still
1232
+ * accepts file drops and folder creation. */
1233
+ this.containerHref = '';
988
1234
  this.locale = navigator.language;
989
1235
  this.containers = [];
990
1236
  this.rootLoading = true;
@@ -996,6 +1242,8 @@ const MrdDocumentList = class {
996
1242
  this.dropTargetId = null;
997
1243
  /** Node id showing an "uploading…" indicator while a dropped file is processed. */
998
1244
  this.uploadingNodeId = null;
1245
+ /** Whether a drag is hovering the root drop-zone (single-container area highlight). */
1246
+ this.rootDropActive = false;
999
1247
  this.nodeIndex = new Map();
1000
1248
  // ── New-folder editing state ───────────────────────────────────────────────
1001
1249
  /** The pending node whose inline name input is open (null = not creating). */
@@ -1029,7 +1277,7 @@ const MrdDocumentList = class {
1029
1277
  return;
1030
1278
  const { target, container } = resolved;
1031
1279
  const tempId = `${container.id}/__new__${this.newFolderSeq++}`;
1032
- const node = this.makeFolderNode(tempId, '', container.id);
1280
+ const node = makeFolderNode(tempId, '', container.id);
1033
1281
  node.pending = true;
1034
1282
  node.editing = true;
1035
1283
  target.children = [...target.children, node];
@@ -1120,8 +1368,18 @@ const MrdDocumentList = class {
1120
1368
  e.preventDefault();
1121
1369
  if (e.dataTransfer)
1122
1370
  e.dataTransfer.dropEffect = file ? 'copy' : 'move';
1371
+ if (!this.rootDropActive)
1372
+ this.rootDropActive = true;
1373
+ };
1374
+ this.onRootDragLeave = (e) => {
1375
+ const related = e.relatedTarget;
1376
+ if (related && this.el.contains(related))
1377
+ return; // moved onto a child, still inside
1378
+ if (this.rootDropActive)
1379
+ this.rootDropActive = false;
1123
1380
  };
1124
1381
  this.onRootDrop = (e) => {
1382
+ this.rootDropActive = false;
1125
1383
  if (!this.singleContainer)
1126
1384
  return;
1127
1385
  const only = this.containers[0];
@@ -1138,7 +1396,33 @@ const MrdDocumentList = class {
1138
1396
  };
1139
1397
  }
1140
1398
  componentDidLoad() {
1141
- this.emitContainerDistinct();
1399
+ if (this.isSeededSingleContainer()) {
1400
+ this.seedSingleContainer();
1401
+ }
1402
+ else {
1403
+ this.emitContainerDistinct();
1404
+ }
1405
+ }
1406
+ /** True when the view is a single-container context: a RELATED_VIEW whose
1407
+ * `inverseRelation` matches the archetype `container` slot, with a known
1408
+ * parent href. The container is then implied by context (not by distinct),
1409
+ * so it works even with zero documents. */
1410
+ isSeededSingleContainer() {
1411
+ var _a, _b;
1412
+ return (((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === index$1.ClientLayoutItemType.RELATED_VIEW &&
1413
+ !!((_b = this.item) === null || _b === void 0 ? void 0 : _b.inverseRelation) &&
1414
+ this.item.inverseRelation === this.containerField &&
1415
+ !!this.containerHref);
1416
+ }
1417
+ /** Seed the single implied container from context and load its folders. */
1418
+ seedSingleContainer() {
1419
+ const node = makeContainerNode(this.containerHref, this.containerField, 0);
1420
+ this.nodeIndex.set(node.id, node);
1421
+ this.containers = [node];
1422
+ this.rootLoading = false;
1423
+ this.singleContainer = true;
1424
+ node.open = true;
1425
+ this.emitFolderDistinct(node);
1142
1426
  }
1143
1427
  componentDidRender() {
1144
1428
  if (this.pendingNeedsFocus && this.pendingInputEl) {
@@ -1174,50 +1458,42 @@ const MrdDocumentList = class {
1174
1458
  return (_b = (_a = this.archetype) === null || _a === void 0 ? void 0 : _a.slots) === null || _b === void 0 ? void 0 : _b.date;
1175
1459
  }
1176
1460
  // ── Path / query building (mirrors mrd-table conventions) ────────────────
1177
- /** VIEW: `/{dataClass}`; RELATED_VIEW: `/{fromClass}/{parentId}/{dataClass}`. */
1461
+ /** VIEW: `/{dataClass}`; RELATED_VIEW: `/{fromClass}/{parentId}/{dataClass}`.
1462
+ * Used for reads (list/distinct): `dataClass`/`relatedClass` may be an abstract
1463
+ * type (e.g. "contents"), filtered down to the concrete `filterClass` via the
1464
+ * `type` query param — see baseParams(). */
1178
1465
  buildDataPath() {
1466
+ var _a, _b;
1467
+ const it = this.item;
1468
+ return buildListPath({
1469
+ isRelatedView: (it === null || it === void 0 ? void 0 : it.type) === index$1.ClientLayoutItemType.RELATED_VIEW,
1470
+ fromClass: it === null || it === void 0 ? void 0 : it.fromClass,
1471
+ parentId: this.parentId,
1472
+ dataClass: (_b = (_a = it === null || it === void 0 ? void 0 : it.dataClass) !== null && _a !== void 0 ? _a : it === null || it === void 0 ? void 0 : it.relatedClass) !== null && _b !== void 0 ? _b : '',
1473
+ });
1474
+ }
1475
+ /** Path for creating a new document (file-drop). Unlike buildDataPath(), this
1476
+ * must target the concrete type: `dataClass`/`relatedClass` can be an abstract
1477
+ * base type (e.g. "contents") that cannot be POSTed to directly, so prefer
1478
+ * `filterClass` (e.g. "documents") when present. */
1479
+ buildCreatePath() {
1179
1480
  var _a, _b, _c;
1180
1481
  const it = this.item;
1181
- const dataClass = (_b = (_a = it === null || it === void 0 ? void 0 : it.dataClass) !== null && _a !== void 0 ? _a : it === null || it === void 0 ? void 0 : it.relatedClass) !== null && _b !== void 0 ? _b : '';
1182
- if ((it === null || it === void 0 ? void 0 : it.type) === index$1.ClientLayoutItemType.RELATED_VIEW) {
1183
- return `/${(_c = it.fromClass) !== null && _c !== void 0 ? _c : ''}/${this.parentId}/${dataClass}`;
1184
- }
1185
- return `/${dataClass}`;
1482
+ return buildListPath({
1483
+ isRelatedView: (it === null || it === void 0 ? void 0 : it.type) === index$1.ClientLayoutItemType.RELATED_VIEW,
1484
+ fromClass: it === null || it === void 0 ? void 0 : it.fromClass,
1485
+ parentId: this.parentId,
1486
+ dataClass: (_c = (_b = (_a = it === null || it === void 0 ? void 0 : it.filterClass) !== null && _a !== void 0 ? _a : it === null || it === void 0 ? void 0 : it.dataClass) !== null && _b !== void 0 ? _b : it === null || it === void 0 ? void 0 : it.relatedClass) !== null && _c !== void 0 ? _c : '',
1487
+ });
1186
1488
  }
1187
1489
  /** View-level static filters + filterClass, shared by every request. */
1188
1490
  baseParams() {
1189
- var _a, _b, _c, _d, _e, _f, _g;
1491
+ var _a, _b, _c;
1190
1492
  const p = new URLSearchParams();
1191
1493
  const filterClass = (_a = this.item) === null || _a === void 0 ? void 0 : _a.filterClass;
1192
1494
  if (filterClass)
1193
1495
  p.set('type', filterClass);
1194
- for (const f of ((_d = (_c = (_b = this.item) === null || _b === void 0 ? void 0 : _b.view) === null || _c === void 0 ? void 0 : _c.filter) !== null && _d !== void 0 ? _d : [])) {
1195
- if (!f.name)
1196
- continue;
1197
- if (f.operator === 'EMPTY') {
1198
- p.set(f.name, '');
1199
- continue;
1200
- }
1201
- if (f.operator === 'NOT_EMPTY') {
1202
- p.set(f.name + '_notempty', 'true');
1203
- continue;
1204
- }
1205
- if (f.operator === 'STARTS_WITH') {
1206
- p.set(f.name + '_startswith', String((_e = f.value) !== null && _e !== void 0 ? _e : ''));
1207
- continue;
1208
- }
1209
- if (f.operator === 'FROM') {
1210
- p.set(f.name + '_from', String((_f = f.value) !== null && _f !== void 0 ? _f : ''));
1211
- continue;
1212
- }
1213
- if (f.operator === 'TO') {
1214
- p.set(f.name + '_to', String((_g = f.value) !== null && _g !== void 0 ? _g : ''));
1215
- continue;
1216
- }
1217
- if (f.value != null) {
1218
- p.set(f.name, String(f.value));
1219
- }
1220
- }
1496
+ applyViewFilters(p, (_c = (_b = this.item) === null || _b === void 0 ? void 0 : _b.view) === null || _c === void 0 ? void 0 : _c.filter);
1221
1497
  return p;
1222
1498
  }
1223
1499
  emitContainerDistinct() {
@@ -1284,7 +1560,7 @@ const MrdDocumentList = class {
1284
1560
  if (!v.value || typeof v.value !== 'object')
1285
1561
  continue;
1286
1562
  const href = v.value.href;
1287
- const node = this.makeContainerNode(href, v.value.name, v.count);
1563
+ const node = makeContainerNode(href, v.value.name, v.count);
1288
1564
  nodes.push(node);
1289
1565
  this.nodeIndex.set(node.id, node);
1290
1566
  }
@@ -1302,38 +1578,7 @@ const MrdDocumentList = class {
1302
1578
  const container = this.nodeIndex.get(containerId);
1303
1579
  if (!container)
1304
1580
  return;
1305
- container.children = [];
1306
- container.hasDocs = false;
1307
- container.docCount = 0;
1308
- for (const v of values) {
1309
- const raw = typeof v.value === 'string' ? v.value : v.value == null ? '' : String(v.value);
1310
- const segs = this.splitFolder(raw);
1311
- if (segs.length === 0) {
1312
- // Root documents — the container's own direct documents.
1313
- container.hasDocs = true;
1314
- container.docCount = v.count;
1315
- container.fullPath = raw;
1316
- continue;
1317
- }
1318
- let node = container;
1319
- const acc = [];
1320
- for (const seg of segs) {
1321
- acc.push(seg);
1322
- let child = node.children.find(c => c.label === seg);
1323
- if (!child) {
1324
- child = this.makeFolderNode(container.id + '/' + acc.join('/'), seg, container.id);
1325
- node.children.push(child);
1326
- this.nodeIndex.set(child.id, child);
1327
- }
1328
- node = child;
1329
- }
1330
- node.hasDocs = true;
1331
- node.docCount = v.count;
1332
- node.fullPath = raw;
1333
- }
1334
- this.computeTotals(container);
1335
- container.foldersLoaded = true;
1336
- container.loading = false;
1581
+ applyFolderDistinct(container, values, this.nodeIndex);
1337
1582
  // If the container has root documents, load them now (they show inline on expand).
1338
1583
  if (container.hasDocs && !container.docsLoaded) {
1339
1584
  this.emitDocuments(container, container);
@@ -1341,36 +1586,6 @@ const MrdDocumentList = class {
1341
1586
  this.bump();
1342
1587
  }
1343
1588
  // ── Tree helpers ─────────────────────────────────────────────────────────
1344
- /** Normalise a folder path: null/""/"/" → root ([]); else split on "/" dropping empties. */
1345
- splitFolder(path) {
1346
- if (path == null)
1347
- return [];
1348
- const s = String(path).trim();
1349
- if (s === '' || s === '/')
1350
- return [];
1351
- return s.split('/').map(x => x.trim()).filter(Boolean);
1352
- }
1353
- makeContainerNode(href, label, count) {
1354
- return {
1355
- id: 'c:' + href, kind: 'container', label, href,
1356
- hasDocs: false, docCount: 0, totalCount: count, children: [],
1357
- open: false, loading: false, foldersLoaded: false, docsLoaded: false, docs: [],
1358
- };
1359
- }
1360
- makeFolderNode(id, label, containerId) {
1361
- return {
1362
- id, kind: 'folder', label, containerId,
1363
- hasDocs: false, docCount: 0, totalCount: 0, children: [],
1364
- open: false, loading: false, foldersLoaded: false, docsLoaded: false, docs: [],
1365
- };
1366
- }
1367
- computeTotals(node) {
1368
- let total = node.docCount;
1369
- for (const c of node.children)
1370
- total += this.computeTotals(c);
1371
- node.totalCount = total;
1372
- return total;
1373
- }
1374
1589
  /** Force a re-render after mutating nodes in place. */
1375
1590
  bump() {
1376
1591
  this.containers = [...this.containers];
@@ -1420,14 +1635,6 @@ const MrdDocumentList = class {
1420
1635
  async createFolder() {
1421
1636
  this.startCreateFolder();
1422
1637
  }
1423
- /** Folder path segments of a node relative to its container (derived from its id). */
1424
- segmentsOf(node, container) {
1425
- if (node.kind === 'container')
1426
- return [];
1427
- const prefix = container.id + '/';
1428
- const rest = node.id.startsWith(prefix) ? node.id.slice(prefix.length) : '';
1429
- return rest ? rest.split('/') : [];
1430
- }
1431
1638
  commitFolder() {
1432
1639
  const node = this.pendingNode;
1433
1640
  const parent = this.pendingParent;
@@ -1452,7 +1659,7 @@ const MrdDocumentList = class {
1452
1659
  }
1453
1660
  // Finalise: swap the temp id for the real path-derived id so a later distinct
1454
1661
  // value with the same folder string merges onto this node.
1455
- const segs = [...this.segmentsOf(parent, container), name];
1662
+ const segs = [...segmentsOf(parent, container), name];
1456
1663
  this.nodeIndex.delete(node.id);
1457
1664
  node.id = container.id + '/' + segs.join('/');
1458
1665
  node.fullPath = '/' + segs.join('/');
@@ -1501,10 +1708,6 @@ const MrdDocumentList = class {
1501
1708
  this.bump();
1502
1709
  this.mrdUpload.emit({ file });
1503
1710
  }
1504
- /** Strip a single trailing extension for the document title. */
1505
- stripExtension(name) {
1506
- return name.replace(/\.[^./\\]+$/, '');
1507
- }
1508
1711
  /** Host callback with the uploaded file reference. Builds the create payload
1509
1712
  * from the archetype slots and requests the new document. */
1510
1713
  async setFileReference(uri) {
@@ -1512,16 +1715,20 @@ const MrdDocumentList = class {
1512
1715
  if (!up)
1513
1716
  return;
1514
1717
  const { file, node, container } = up;
1515
- const folder = this.folderStringOf(node, container);
1718
+ const folder = folderStringOf(node, container);
1516
1719
  const values = {
1517
1720
  [this.fileField]: uri,
1518
- [this.titleField]: this.stripExtension(file.name),
1721
+ [this.titleField]: stripExtension(file.name),
1519
1722
  [this.folderField]: folder,
1520
- [this.containerField]: container.href,
1521
1723
  };
1522
- this.mrdCreateObject.emit({ path: this.buildDataPath(), values });
1724
+ // The create path already embeds the container (/{fromClass}/{parentId}/...)
1725
+ // when this is the seeded single-container context; omit the redundant field.
1726
+ if (!this.isSeededSingleContainer()) {
1727
+ values[this.containerField] = container.href;
1728
+ }
1729
+ this.mrdCreateObject.emit({ path: this.buildCreatePath(), values });
1523
1730
  // Optimistically show the new document (no href until a reload).
1524
- const optimistic = { [this.titleField]: this.stripExtension(file.name), _optimistic: true };
1731
+ const optimistic = { [this.titleField]: stripExtension(file.name), _optimistic: true };
1525
1732
  const wasUnloadedEmpty = !node.docsLoaded && node.docCount === 0;
1526
1733
  node.hasDocs = true;
1527
1734
  node.pending = false;
@@ -1550,16 +1757,6 @@ const MrdDocumentList = class {
1550
1757
  this.lastOptimisticDoc = null;
1551
1758
  this.bump();
1552
1759
  }
1553
- /** Folder string a node represents: the raw distinct value when it holds
1554
- * documents, else derived from its path segments; null for a container root. */
1555
- folderStringOf(node, container) {
1556
- if (node.kind === 'container')
1557
- return null;
1558
- if (node.fullPath != null && node.fullPath !== '')
1559
- return node.fullPath;
1560
- const segs = this.segmentsOf(node, container);
1561
- return segs.length ? '/' + segs.join('/') : null;
1562
- }
1563
1760
  moveDocument(toNode, toContainer) {
1564
1761
  var _a, _b;
1565
1762
  const doc = this.dragDoc;
@@ -1571,26 +1768,14 @@ const MrdDocumentList = class {
1571
1768
  : (fromNode.containerId ? this.nodeIndex.get(fromNode.containerId) : undefined);
1572
1769
  if (!fromContainer)
1573
1770
  return;
1574
- const targetFolder = this.folderStringOf(toNode, toContainer);
1575
- const sourceFolder = this.folderStringOf(fromNode, fromContainer);
1771
+ const targetFolder = folderStringOf(toNode, toContainer);
1772
+ const sourceFolder = folderStringOf(fromNode, fromContainer);
1576
1773
  const sameContainer = toContainer === fromContainer;
1577
1774
  // No-op: dropped back onto its own folder.
1578
1775
  if (toNode === fromNode || (sameContainer && targetFolder === sourceFolder))
1579
1776
  return;
1580
- // ── Optimistic tree update (fire-and-forget; no refetch) ──
1581
- fromNode.docs = fromNode.docs.filter(d => d !== doc);
1582
- fromNode.docCount = Math.max(0, fromNode.docCount - 1);
1583
- // A now-empty folder should stop showing an expand chevron (it disappears on
1584
- // the next reload anyway, since it is derived from document folder strings).
1585
- if (fromNode.docsLoaded)
1586
- fromNode.hasDocs = fromNode.docs.length > 0;
1587
- toNode.hasDocs = true;
1588
- toNode.pending = false; // a pending folder is now materialised
1589
- toNode.docCount += 1;
1590
- if (toNode.kind === 'folder')
1591
- toNode.fullPath = targetFolder !== null && targetFolder !== void 0 ? targetFolder : '';
1592
- if (toNode.docsLoaded)
1593
- toNode.docs = [...toNode.docs, doc];
1777
+ // Optimistic tree update (fire-and-forget; no refetch).
1778
+ applyDocMove(doc, fromNode, toNode, targetFolder);
1594
1779
  this.recomputeContainerTotals(fromContainer, -1);
1595
1780
  if (!sameContainer)
1596
1781
  this.recomputeContainerTotals(toContainer, 1);
@@ -1608,7 +1793,7 @@ const MrdDocumentList = class {
1608
1793
  * loaded; otherwise just nudge the aggregate badge by the delta. */
1609
1794
  recomputeContainerTotals(container, delta) {
1610
1795
  if (container.foldersLoaded) {
1611
- this.computeTotals(container);
1796
+ computeTotals(container);
1612
1797
  }
1613
1798
  else {
1614
1799
  container.totalCount = Math.max(0, container.totalCount + delta);
@@ -1621,105 +1806,64 @@ const MrdDocumentList = class {
1621
1806
  this.mrdNavigate.emit({ href, label });
1622
1807
  }
1623
1808
  // ── Render ───────────────────────────────────────────────────────────────
1624
- renderChevron(open, leaf) {
1625
- return (index.h("span", { class: `mrd-document-list__chev${leaf ? ' mrd-document-list__chev--leaf' : ''}${open ? ' mrd-document-list__chev--open' : ''}` }, index.h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, index.h("path", { d: "M9 6l6 6-6 6" }))));
1626
- }
1627
- renderDossierIcon() {
1628
- return (index.h("svg", { class: "mrd-document-list__icon mrd-document-list__icon--dossier", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, index.h("path", { d: "M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" })));
1629
- }
1630
- renderFolderIcon() {
1631
- return (index.h("svg", { class: "mrd-document-list__icon mrd-document-list__icon--folder", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, index.h("path", { d: "M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" })));
1632
- }
1633
- renderDocIcon() {
1634
- return (index.h("svg", { class: "mrd-document-list__icon mrd-document-list__icon--doc", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, index.h("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }), index.h("path", { d: "M14 2v6h6" })));
1635
- }
1636
- indent(depth) {
1637
- return index.h("span", { class: "mrd-document-list__indent", style: { width: `${depth * 18}px` } });
1638
- }
1639
- renderDocRow(doc, node, container, depth) {
1640
- var _a, _b, _c, _d, _e;
1641
- const label = (_b = (_a = doc === null || doc === void 0 ? void 0 : doc[this.titleField]) !== null && _a !== void 0 ? _a : doc === null || doc === void 0 ? void 0 : doc.name) !== null && _b !== void 0 ? _b : '';
1642
- const dateRaw = this.dateField ? doc === null || doc === void 0 ? void 0 : doc[this.dateField] : undefined;
1643
- const date = dateRaw ? formatDate(dateRaw, this.locale) : '';
1644
- return (index.h("div", { class: "mrd-document-list__row mrd-document-list__row--doc", key: (_e = (_d = (_c = doc === null || doc === void 0 ? void 0 : doc._links) === null || _c === void 0 ? void 0 : _c.self) === null || _d === void 0 ? void 0 : _d.href) !== null && _e !== void 0 ? _e : label, draggable: true, onClick: () => this.openDoc(doc), onDragStart: (e) => this.onDocDragStart(e, doc, node), onDragEnd: this.onDocDragEnd, onDragOver: (e) => this.onNodeDragOver(e, node), onDragLeave: () => this.onNodeDragLeave(node), onDrop: (e) => this.onNodeDrop(e, node, container) }, this.indent(depth), this.renderChevron(false, true), this.renderDocIcon(), index.h("span", { class: "mrd-document-list__label" }, label), date && index.h("span", { class: "mrd-document-list__date" }, date)));
1645
- }
1646
- renderLoadingRow(depth) {
1647
- return (index.h("div", { class: "mrd-document-list__loading", key: "loading" }, this.indent(depth), index.h("span", { class: "mrd-document-list__spinner" }), t('loading', this.locale)));
1648
- }
1649
- renderChildren(container, node, depth) {
1650
- const out = [];
1651
- // Direct documents of this node (root docs live on the container node).
1652
- if (node.hasDocs) {
1653
- if (node.docsLoaded) {
1654
- for (const doc of node.docs)
1655
- out.push(this.renderDocRow(doc, node, container, depth));
1656
- }
1657
- else if (node.loading) {
1658
- out.push(this.renderLoadingRow(depth));
1659
- }
1660
- }
1661
- // Child folders.
1662
- for (const child of node.children) {
1663
- out.push(this.renderFolderNode(container, child, depth));
1664
- }
1665
- // An uploading file dropped onto this node.
1666
- if (node.id === this.uploadingNodeId)
1667
- out.push(this.renderUploadingRow(depth));
1668
- return out;
1669
- }
1670
- renderUploadingRow(depth) {
1671
- return (index.h("div", { class: "mrd-document-list__loading", key: "uploading" }, this.indent(depth), index.h("span", { class: "mrd-document-list__spinner" }), t('upload_file', this.locale)));
1672
- }
1673
- renderFolderEditRow(node, depth) {
1674
- return (index.h("div", { class: "mrd-document-list__node", key: node.id }, index.h("div", { class: "mrd-document-list__row mrd-document-list__row--edit" }, this.indent(depth), this.renderChevron(false, true), this.renderFolderIcon(), index.h("input", { class: "mrd-document-list__name-input", type: "text", placeholder: t('folder_name_placeholder', this.locale), ref: el => (this.pendingInputEl = el), onInput: this.onPendingInput, onKeyDown: this.onPendingKeyDown, onBlur: () => this.cancelFolder() })), node.error && (index.h("div", { class: "mrd-document-list__error", style: { paddingLeft: `${depth * 18 + 52}px` } }, node.error))));
1675
- }
1676
- renderFolderNode(container, node, depth) {
1677
- if (node.editing)
1678
- return this.renderFolderEditRow(node, depth);
1679
- const leaf = node.children.length === 0 && !node.hasDocs;
1680
- const selected = node.id === this.selectedId;
1681
- const cls = 'mrd-document-list__row'
1682
- + (selected ? ' mrd-document-list__row--selected' : '')
1683
- + (node.pending ? ' mrd-document-list__row--pending' : '')
1684
- + (node.id === this.dropTargetId ? ' mrd-document-list__row--drop' : '');
1685
- return (index.h("div", { class: "mrd-document-list__node", key: node.id }, index.h("div", { class: cls, onClick: () => this.toggleFolder(container, node), onDragOver: (e) => this.onNodeDragOver(e, node), onDragLeave: () => this.onNodeDragLeave(node), onDrop: (e) => this.onNodeDrop(e, node, container) }, this.indent(depth), this.renderChevron(node.open, leaf), this.renderFolderIcon(), index.h("span", { class: "mrd-document-list__label" }, node.label), index.h("span", { class: "mrd-document-list__count" }, node.totalCount)), node.open && index.h("div", { class: "mrd-document-list__kids" }, this.renderChildren(container, node, depth + 1))));
1686
- }
1687
- renderContainerNode(node, depth) {
1688
- const selected = node.id === this.selectedId;
1689
- const cls = 'mrd-document-list__row mrd-document-list__row--dossier'
1690
- + (selected ? ' mrd-document-list__row--selected' : '')
1691
- + (node.id === this.dropTargetId ? ' mrd-document-list__row--drop' : '');
1692
- return (index.h("div", { class: "mrd-document-list__node", key: node.id }, index.h("div", { class: cls, onClick: () => this.toggleContainer(node), onDragOver: (e) => this.onNodeDragOver(e, node), onDragLeave: () => this.onNodeDragLeave(node), onDrop: (e) => this.onNodeDrop(e, node, node) }, this.indent(depth), this.renderChevron(node.open, false), this.renderDossierIcon(), index.h("span", { class: "mrd-document-list__label" }, node.label), index.h("span", { class: "mrd-document-list__count" }, node.totalCount)), node.open && (index.h("div", { class: "mrd-document-list__kids" }, node.loading && !node.foldersLoaded
1693
- ? this.renderLoadingRow(depth + 1)
1694
- : this.renderChildren(node, node, depth + 1)))));
1809
+ treeCtx() {
1810
+ return {
1811
+ locale: this.locale,
1812
+ titleField: this.titleField,
1813
+ dateField: this.dateField,
1814
+ selectedId: this.selectedId,
1815
+ dropTargetId: this.dropTargetId,
1816
+ uploadingNodeId: this.uploadingNodeId,
1817
+ on: {
1818
+ toggleContainer: node => this.toggleContainer(node),
1819
+ toggleFolder: (container, node) => this.toggleFolder(container, node),
1820
+ openDoc: doc => this.openDoc(doc),
1821
+ docDragStart: this.onDocDragStart,
1822
+ docDragEnd: this.onDocDragEnd,
1823
+ nodeDragOver: this.onNodeDragOver,
1824
+ nodeDragLeave: this.onNodeDragLeave,
1825
+ nodeDrop: this.onNodeDrop,
1826
+ pendingInput: this.onPendingInput,
1827
+ pendingKeyDown: this.onPendingKeyDown,
1828
+ cancelFolder: () => this.cancelFolder(),
1829
+ setPendingInputEl: el => (this.pendingInputEl = el),
1830
+ },
1831
+ };
1695
1832
  }
1696
1833
  render() {
1834
+ const ctx = this.treeCtx();
1697
1835
  let body;
1698
1836
  if (this.rootLoading) {
1699
- body = this.renderLoadingRow(0);
1837
+ body = renderLoadingRow(ctx, 0);
1700
1838
  }
1701
1839
  else if (this.containers.length === 0) {
1702
- body = index.h("div", { key: 'b8c3297cd7cff5bf79ce694d2ee1a64c570df5ce', class: "mrd-document-list__empty" }, t('no_results', this.locale));
1840
+ body = index.h("div", { key: 'ce40dab51ab61447838e5059159ae4778209a6f3', class: "mrd-document-list__empty" }, t('no_results', this.locale));
1703
1841
  }
1704
1842
  else if (this.singleContainer) {
1705
1843
  // Dossier context: render the single container's folder tree at the root.
1706
1844
  const only = this.containers[0];
1707
- body = only.loading && !only.foldersLoaded
1708
- ? this.renderLoadingRow(0)
1709
- : this.renderChildren(only, only, 0);
1845
+ if (only.loading && !only.foldersLoaded) {
1846
+ body = renderLoadingRow(ctx, 0);
1847
+ }
1848
+ else {
1849
+ const kids = renderNodeChildren(ctx, only, only, 0);
1850
+ body = kids.length
1851
+ ? kids
1852
+ : index.h("div", { class: "mrd-document-list__empty" }, t('doc_empty_drop', this.locale));
1853
+ }
1710
1854
  }
1711
1855
  else {
1712
- body = this.containers.map(c => this.renderContainerNode(c, 0));
1856
+ body = this.containers.map(c => renderContainerNode(ctx, c, 0));
1713
1857
  }
1714
- return (index.h(index.Host, { key: 'ff3b024a79ba2270aa28861923bc6406f98061aa' }, index.h("div", { key: '9db121e5336a4e3c82443257f6424db5ab4f0baf', class: "mrd-document-list", onDragOver: this.onRootDragOver, onDrop: this.onRootDrop }, body)));
1858
+ return (index.h(index.Host, { key: '9e1f7805ae18bce506c530a481db902900ad95f3' }, index.h("div", { key: 'a51334634e94310a71650ad49f17f0a20e2aed4d', class: 'mrd-document-list' + (this.rootDropActive ? ' mrd-document-list--drop-active' : ''), onDragOver: this.onRootDragOver, onDragLeave: this.onRootDragLeave, onDrop: this.onRootDrop }, body)));
1715
1859
  }
1716
1860
  get el() { return index.getElement(this); }
1717
1861
  };
1718
1862
  /** Root sentinel id for the container-level distinct request. */
1719
1863
  MrdDocumentList.ROOT = '__root__';
1720
- MrdDocumentList.style = mrdDocumentListScss();
1864
+ MrdDocumentList.style = mrdDocumentListCss();
1721
1865
 
1722
- const mrdDocumentViewScss = () => `.sc-mrd-document-view-h{display:block}.mrd-document-view.sc-mrd-document-view{max-width:720px}.mrd-document-view__crumb.sc-mrd-document-view{display:inline-flex;align-items:center;gap:var(--mrd-space-2);margin-bottom:var(--mrd-space-4);padding:var(--mrd-space-1) var(--mrd-space-3);background:var(--mrd-color-primary-light);border:1px solid transparent;border-radius:var(--mrd-border-radius);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-primary-dark);cursor:pointer}.mrd-document-view__crumb.sc-mrd-document-view:hover{border-color:var(--mrd-color-primary)}.mrd-document-view__crumb-icon.sc-mrd-document-view{width:0.875rem;height:0.875rem;flex-shrink:0}.mrd-document-view__title.sc-mrd-document-view{font-size:var(--mrd-font-size-2xl);font-weight:var(--mrd-font-weight-bold);color:var(--mrd-color-neutral-900);letter-spacing:-0.02em;margin:0 0 var(--mrd-space-1) 0}.mrd-document-view__date.sc-mrd-document-view{font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-400);font-variant-numeric:tabular-nums;margin:0 0 var(--mrd-space-6) 0}.mrd-document-view__file.sc-mrd-document-view{display:flex;align-items:center;gap:var(--mrd-space-4);padding:var(--mrd-space-4);border:1px solid var(--mrd-border-color);border-radius:var(--mrd-border-radius-md);background:var(--mrd-color-neutral-50);margin-bottom:var(--mrd-space-6)}.mrd-document-view__file-preview.sc-mrd-document-view{width:2.875rem;height:3.625rem;flex-shrink:0;display:grid;place-items:center;border-radius:var(--mrd-border-radius-sm);background:var(--mrd-color-white);border:1px solid var(--mrd-border-color);color:var(--mrd-color-danger);box-shadow:var(--mrd-shadow-sm)}.mrd-document-view__file-preview.sc-mrd-document-view svg.sc-mrd-document-view{width:1.5rem;height:1.5rem}.mrd-document-view__file-meta.sc-mrd-document-view{flex:1;min-width:0}.mrd-document-view__file-name.sc-mrd-document-view{font-weight:var(--mrd-font-weight-semibold);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-800);word-break:break-word}.mrd-document-view__download.sc-mrd-document-view{display:inline-flex;align-items:center;gap:var(--mrd-space-2);flex-shrink:0;height:2rem;padding:0 var(--mrd-space-3);background:var(--mrd-color-white);border:1px solid var(--mrd-color-neutral-300);border-radius:var(--mrd-border-radius);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-medium);color:var(--mrd-color-neutral-700);cursor:pointer}.mrd-document-view__download.sc-mrd-document-view:hover{background:var(--mrd-color-neutral-100);color:var(--mrd-color-neutral-900)}.mrd-document-view__download.sc-mrd-document-view svg.sc-mrd-document-view{width:0.9375rem;height:0.9375rem}.mrd-document-view__summary-body.sc-mrd-document-view{font-size:var(--mrd-font-size-base);color:var(--mrd-color-neutral-700);line-height:var(--mrd-line-height-relaxed)}`;
1866
+ const mrdDocumentViewCss = () => `.sc-mrd-document-view-h{display:block}.mrd-document-view.sc-mrd-document-view{max-width:720px}.mrd-document-view__crumb.sc-mrd-document-view{display:inline-flex;align-items:center;gap:var(--mrd-space-2);margin-bottom:var(--mrd-space-4);padding:var(--mrd-space-1) var(--mrd-space-3);background:var(--mrd-color-primary-light);border:1px solid transparent;border-radius:var(--mrd-border-radius);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-primary-dark);cursor:pointer}.mrd-document-view__crumb.sc-mrd-document-view:hover{border-color:var(--mrd-color-primary)}.mrd-document-view__crumb-icon.sc-mrd-document-view{width:0.875rem;height:0.875rem;flex-shrink:0}.mrd-document-view__title.sc-mrd-document-view{font-size:var(--mrd-font-size-2xl);font-weight:var(--mrd-font-weight-bold);color:var(--mrd-color-neutral-900);letter-spacing:-0.02em;margin:0 0 var(--mrd-space-1) 0}.mrd-document-view__date.sc-mrd-document-view{font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-400);font-variant-numeric:tabular-nums;margin:0 0 var(--mrd-space-6) 0}.mrd-document-view__file.sc-mrd-document-view{display:flex;align-items:center;gap:var(--mrd-space-4);padding:var(--mrd-space-4);border:1px solid var(--mrd-border-color);border-radius:var(--mrd-border-radius-md);background:var(--mrd-color-neutral-50);margin-bottom:var(--mrd-space-6)}.mrd-document-view__file-preview.sc-mrd-document-view{width:2.875rem;height:3.625rem;flex-shrink:0;display:grid;place-items:center;border-radius:var(--mrd-border-radius-sm);background:var(--mrd-color-white);border:1px solid var(--mrd-border-color);color:var(--mrd-color-danger);box-shadow:var(--mrd-shadow-sm)}.mrd-document-view__file-preview.sc-mrd-document-view svg.sc-mrd-document-view{width:1.5rem;height:1.5rem}.mrd-document-view__file-meta.sc-mrd-document-view{flex:1;min-width:0}.mrd-document-view__file-name.sc-mrd-document-view{font-weight:var(--mrd-font-weight-semibold);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-800);word-break:break-word}.mrd-document-view__download.sc-mrd-document-view{display:inline-flex;align-items:center;gap:var(--mrd-space-2);flex-shrink:0;height:2rem;padding:0 var(--mrd-space-3);background:var(--mrd-color-white);border:1px solid var(--mrd-color-neutral-300);border-radius:var(--mrd-border-radius);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-medium);color:var(--mrd-color-neutral-700);cursor:pointer}.mrd-document-view__download.sc-mrd-document-view:hover{background:var(--mrd-color-neutral-100);color:var(--mrd-color-neutral-900)}.mrd-document-view__download.sc-mrd-document-view svg.sc-mrd-document-view{width:0.9375rem;height:0.9375rem}.mrd-document-view__summary-body.sc-mrd-document-view{font-size:var(--mrd-font-size-base);color:var(--mrd-color-neutral-700);line-height:var(--mrd-line-height-relaxed)}`;
1723
1867
 
1724
1868
  const MrdDocumentView = class {
1725
1869
  constructor(hostRef) {
@@ -1769,12 +1913,12 @@ const MrdDocumentView = class {
1769
1913
  const date = dateRaw != null && dateRaw !== '' ? formatDate(dateRaw, this.locale) : null;
1770
1914
  const summaryRaw = this.slotValue('summary');
1771
1915
  const summary = summaryRaw != null && summaryRaw !== '' ? String(summaryRaw) : null;
1772
- return (index.h(index.Host, { key: '0a2071925ecdb21738376d66fa4babf4590e694c' }, index.h("div", { key: 'a2d29c0b6e211cab142adc780466bc885a602e96', class: "mrd-document-view" }, this.renderContainer(), title && index.h("h1", { key: '7f5ac202c21bc8a70f0dd15e2e1fa06e651b5bce', class: "mrd-document-view__title" }, title), date && index.h("p", { key: 'b1dce94d5fd8bfd5e078644f631a38f91b87e7ff', class: "mrd-document-view__date" }, date), this.renderFile(), summary && (index.h("div", { key: '588b9ca40a49ae9ea303852620bde75333b440ab', class: "mrd-document-view__summary" }, index.h("div", { key: 'd3b8adb85ac346b72451e789c10aedd539c966de', class: "mrd-document-view__summary-body", innerHTML: summary }))))));
1916
+ return (index.h(index.Host, { key: '0c64c72eaf5e1eefc2ca9aebb2543081eb1eae32' }, index.h("div", { key: '70cce81b089fee81a4c163a6ba5fbcc8cb46131c', class: "mrd-document-view" }, this.renderContainer(), title && index.h("h1", { key: '50f85b32a6740d6cf57fdf1bb0bcc597b5e97b31', class: "mrd-document-view__title" }, title), date && index.h("p", { key: 'b3c8fb3b4382104858d49ef9a1597034665122bb', class: "mrd-document-view__date" }, date), this.renderFile(), summary && (index.h("div", { key: '2046c1eca7601549115de0c95ff778abaf5faf46', class: "mrd-document-view__summary" }, index.h("div", { key: '875863d3e438eee3d4df10473a93f09370fde08c', class: "mrd-document-view__summary-body", innerHTML: summary }))))));
1773
1917
  }
1774
1918
  };
1775
- MrdDocumentView.style = mrdDocumentViewScss();
1919
+ MrdDocumentView.style = mrdDocumentViewCss();
1776
1920
 
1777
- const mrdEmailFieldScss = () => `.sc-mrd-email-field-h{display:block}.mrd-email-field.sc-mrd-email-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-email-field__label.sc-mrd-email-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-email-field__label--required.sc-mrd-email-field::after{content:' *';color:var(--mrd-color-danger)}.mrd-email-field__input.sc-mrd-email-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box}.mrd-email-field__input.sc-mrd-email-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-email-field__input.sc-mrd-email-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-email-field__input.sc-mrd-email-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-email-field__input--error.sc-mrd-email-field{border-color:var(--mrd-border-color-error)}.mrd-email-field__input--error.sc-mrd-email-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-email-field__error.sc-mrd-email-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}`;
1921
+ const mrdEmailFieldCss = () => `.sc-mrd-email-field-h{display:block}.mrd-email-field.sc-mrd-email-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-email-field__label.sc-mrd-email-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-email-field__label--required.sc-mrd-email-field::after{content:" *";color:var(--mrd-color-danger)}.mrd-email-field__input.sc-mrd-email-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box}.mrd-email-field__input.sc-mrd-email-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-email-field__input.sc-mrd-email-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-email-field__input.sc-mrd-email-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-email-field__input--error.sc-mrd-email-field{border-color:var(--mrd-border-color-error)}.mrd-email-field__input--error.sc-mrd-email-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-email-field__error.sc-mrd-email-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}`;
1778
1922
 
1779
1923
  const MrdEmailField = class {
1780
1924
  constructor(hostRef) {
@@ -1795,26 +1939,18 @@ const MrdEmailField = class {
1795
1939
  };
1796
1940
  this.handleBlur = (e) => {
1797
1941
  const val = e.target.value;
1798
- if (this.required && !validateRequired(val)) {
1799
- this.error = t('required', this.locale);
1800
- }
1801
- else if (val && !validateEmail(val)) {
1802
- this.error = t('invalid_email', this.locale);
1803
- }
1804
- else {
1805
- this.error = '';
1806
- }
1942
+ this.error = requiredError(val, this.required, this.locale)
1943
+ || (val && !validateEmail(val) ? t('invalid_email', this.locale) : '');
1807
1944
  this.mrdBlur.emit({ name: this.name, value: val });
1808
1945
  };
1809
1946
  }
1810
1947
  render() {
1811
- const hasError = !!this.error;
1812
- return (index.h(index.Host, { key: '0d442ab2a711c26c83fcdbf0fd8cd006d8dd8649' }, index.h("div", { key: 'ceb2a80679514c4c5b888fe096c90ed6cc973f64', class: "mrd-email-field" }, this.label && (index.h("label", { key: '663f95eff1002ee56cfc3104514bf31b47e26750', class: `mrd-email-field__label${this.required ? ' mrd-email-field__label--required' : ''}` }, this.label)), index.h("input", { key: '42dbdec25a47b37cfd68d00d0b8a481f96fe8241', class: `mrd-email-field__input${hasError ? ' mrd-email-field__input--error' : ''}`, type: "email", name: this.name, value: this.value, placeholder: this.placeholder || 'name@example.com', required: this.required, disabled: this.disabled, onInput: this.handleInput, onBlur: this.handleBlur }), hasError && index.h("span", { key: '626ee856ceaa7051fb9dd1de8b7cbd708e83f617', class: "mrd-email-field__error" }, this.error))));
1948
+ return (index.h(index.Host, { key: '93f7c4975c24e6001e772f2858344edec04cda10' }, index.h("div", { key: '4f49a2a1f68a4161762861c5d54fd3690c88ac5d', class: "mrd-email-field" }, index.h(FieldLabel, { key: '23b20799f3e7c04889b7bc3a271e61b0bb5d7537', base: "mrd-email-field", label: this.label, required: this.required }), index.h("input", { key: '0fc452bfb9295a80102eeed4b32bcc9475c9d17b', class: controlClass('mrd-email-field', !!this.error), type: "email", name: this.name, value: this.value, placeholder: this.placeholder || 'name@example.com', required: this.required, disabled: this.disabled, onInput: this.handleInput, onBlur: this.handleBlur }), index.h(FieldError, { key: '34945fff9c69cf2f0aeb56492c95052250514d5c', base: "mrd-email-field", error: this.error }))));
1813
1949
  }
1814
1950
  };
1815
- MrdEmailField.style = mrdEmailFieldScss();
1951
+ MrdEmailField.style = mrdEmailFieldCss();
1816
1952
 
1817
- const mrdFieldScss = () => `.sc-mrd-field-h{display:block}.mrd-field__inner.sc-mrd-field{display:block;width:100%}.mrd-field__history-editor.sc-mrd-field{margin-top:var(--mrd-space-2);display:flex;flex-direction:column;gap:var(--mrd-space-1)}.mrd-field__history-editor-label.sc-mrd-field{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-xs);font-weight:var(--mrd-font-weight-medium);color:var(--mrd-color-neutral-500)}.mrd-field__history-editor-row.sc-mrd-field{display:flex;align-items:center;gap:var(--mrd-space-2)}.mrd-field__history-editor-sep.sc-mrd-field{flex-shrink:0;font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-500)}.mrd-field__history-editor-value.sc-mrd-field{flex:1 1 0;min-width:0;height:var(--mrd-input-height);padding:0 var(--mrd-space-3);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-800);background-color:var(--mrd-color-white);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius-md);outline:none;transition:border-color var(--mrd-transition-fast), box-shadow var(--mrd-transition-fast)}.mrd-field__history-editor-value.sc-mrd-field:focus{border-color:var(--mrd-color-primary);box-shadow:var(--mrd-shadow-focus)}.mrd-field__history-editor-until.sc-mrd-field{flex:0 0 10rem;height:var(--mrd-input-height);padding:0 var(--mrd-space-3);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-800);background-color:var(--mrd-color-white);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius-md);outline:none;transition:border-color var(--mrd-transition-fast), box-shadow var(--mrd-transition-fast)}.mrd-field__history-editor-until.sc-mrd-field:focus{border-color:var(--mrd-color-primary);box-shadow:var(--mrd-shadow-focus)}.mrd-field__history-editor-remove.sc-mrd-field{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:2rem;height:2rem;padding:0;background:transparent;border:none;border-radius:var(--mrd-border-radius-sm);color:var(--mrd-color-neutral-400);cursor:pointer;transition:color var(--mrd-transition-fast), background-color var(--mrd-transition-fast)}.mrd-field__history-editor-remove.sc-mrd-field:hover{color:var(--mrd-color-danger);background-color:var(--mrd-color-danger-light)}.mrd-field__history-editor-remove.sc-mrd-field svg.sc-mrd-field{width:1rem;height:1rem}.mrd-field__history-editor-add.sc-mrd-field{align-self:flex-start;padding:var(--mrd-space-1) var(--mrd-space-3);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-xs);font-weight:var(--mrd-font-weight-medium);color:var(--mrd-color-primary);background:transparent;border:var(--mrd-border-width) solid var(--mrd-color-primary);border-radius:var(--mrd-border-radius-md);cursor:pointer;transition:background-color var(--mrd-transition-fast), color var(--mrd-transition-fast)}.mrd-field__history-editor-add.sc-mrd-field:hover{background-color:var(--mrd-color-primary-light)}`;
1953
+ const mrdFieldCss = () => `.sc-mrd-field-h{display:block}.mrd-field__inner.sc-mrd-field{display:block;width:100%}.mrd-field__history-editor.sc-mrd-field{margin-top:var(--mrd-space-2);display:flex;flex-direction:column;gap:var(--mrd-space-1)}.mrd-field__history-editor-label.sc-mrd-field{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-xs);font-weight:var(--mrd-font-weight-medium);color:var(--mrd-color-neutral-500)}.mrd-field__history-editor-row.sc-mrd-field{display:flex;align-items:center;gap:var(--mrd-space-2)}.mrd-field__history-editor-sep.sc-mrd-field{flex-shrink:0;font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-500)}.mrd-field__history-editor-value.sc-mrd-field{flex:1 1 0;min-width:0;height:var(--mrd-input-height);padding:0 var(--mrd-space-3);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-800);background-color:var(--mrd-color-white);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius-md);outline:none;transition:border-color var(--mrd-transition-fast), box-shadow var(--mrd-transition-fast)}.mrd-field__history-editor-value.sc-mrd-field:focus{border-color:var(--mrd-color-primary);box-shadow:var(--mrd-shadow-focus)}.mrd-field__history-editor-until.sc-mrd-field{flex:0 0 10rem;height:var(--mrd-input-height);padding:0 var(--mrd-space-3);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-800);background-color:var(--mrd-color-white);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius-md);outline:none;transition:border-color var(--mrd-transition-fast), box-shadow var(--mrd-transition-fast)}.mrd-field__history-editor-until.sc-mrd-field:focus{border-color:var(--mrd-color-primary);box-shadow:var(--mrd-shadow-focus)}.mrd-field__history-editor-remove.sc-mrd-field{display:inline-flex;align-items:center;justify-content:center;flex-shrink:0;width:2rem;height:2rem;padding:0;background:transparent;border:none;border-radius:var(--mrd-border-radius-sm);color:var(--mrd-color-neutral-400);cursor:pointer;transition:color var(--mrd-transition-fast), background-color var(--mrd-transition-fast)}.mrd-field__history-editor-remove.sc-mrd-field:hover{color:var(--mrd-color-danger);background-color:var(--mrd-color-danger-light)}.mrd-field__history-editor-remove.sc-mrd-field svg.sc-mrd-field{width:1rem;height:1rem}.mrd-field__history-editor-add.sc-mrd-field{align-self:flex-start;padding:var(--mrd-space-1) var(--mrd-space-3);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-xs);font-weight:var(--mrd-font-weight-medium);color:var(--mrd-color-primary);background:transparent;border:var(--mrd-border-width) solid var(--mrd-color-primary);border-radius:var(--mrd-border-radius-md);cursor:pointer;transition:background-color var(--mrd-transition-fast), color var(--mrd-transition-fast)}.mrd-field__history-editor-add.sc-mrd-field:hover{background-color:var(--mrd-color-primary-light)}`;
1818
1954
 
1819
1955
  const MrdField = class {
1820
1956
  constructor(hostRef) {
@@ -1999,9 +2135,47 @@ const MrdField = class {
1999
2135
  }]
2000
2136
  }; }
2001
2137
  };
2002
- MrdField.style = mrdFieldScss();
2138
+ MrdField.style = mrdFieldCss();
2003
2139
 
2004
- const mrdFileFieldScss = () => `.sc-mrd-file-field-h{display:block}.mrd-file-field.sc-mrd-file-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-file-field__label.sc-mrd-file-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-file-field__label--required.sc-mrd-file-field::after{content:' *';color:var(--mrd-color-danger)}.mrd-file-field__zone.sc-mrd-file-field{display:flex;align-items:center;justify-content:center;padding:var(--mrd-space-6);border:2px dashed var(--mrd-border-color);border-radius:var(--mrd-border-radius-md);background-color:var(--mrd-color-neutral-50);cursor:pointer;transition:border-color var(--mrd-transition), background-color var(--mrd-transition);min-height:100px;position:relative}.mrd-file-field__zone.sc-mrd-file-field:hover{border-color:var(--mrd-color-primary);background-color:var(--mrd-color-primary-light)}.mrd-file-field__zone--dragging.sc-mrd-file-field{border-color:var(--mrd-color-primary);background-color:var(--mrd-color-primary-light)}.mrd-file-field__zone--error.sc-mrd-file-field{border-color:var(--mrd-border-color-error)}.mrd-file-field__zone--disabled.sc-mrd-file-field{opacity:0.6;cursor:not-allowed}.mrd-file-field__zone--disabled.sc-mrd-file-field:hover{border-color:var(--mrd-border-color);background-color:var(--mrd-color-neutral-50)}.mrd-file-field__input.sc-mrd-file-field{position:absolute;inset:0;opacity:0;width:100%;height:100%;cursor:pointer;pointer-events:none}.mrd-file-field__prompt.sc-mrd-file-field{display:flex;flex-direction:column;align-items:center;gap:var(--mrd-space-2);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-500);text-align:center}.mrd-file-field__upload-icon.sc-mrd-file-field{width:32px;height:32px;color:var(--mrd-color-neutral-400)}.mrd-file-field__browse.sc-mrd-file-field{color:var(--mrd-color-primary);font-weight:var(--mrd-font-weight-medium);text-decoration:underline}.mrd-file-field__selected.sc-mrd-file-field{display:flex;align-items:center;gap:var(--mrd-space-2);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-700)}.mrd-file-field__icon.sc-mrd-file-field{width:20px;height:20px;color:var(--mrd-color-primary);flex-shrink:0}.mrd-file-field__filename.sc-mrd-file-field{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:200px}.mrd-file-field__clear.sc-mrd-file-field{background:none;border:none;cursor:pointer;color:var(--mrd-color-neutral-400);font-size:var(--mrd-font-size-sm);padding:var(--mrd-space-1);border-radius:var(--mrd-border-radius-sm);line-height:1}.mrd-file-field__clear.sc-mrd-file-field:hover{color:var(--mrd-color-danger);background-color:var(--mrd-color-danger-light)}.mrd-file-field__spinner.sc-mrd-file-field{display:inline-block;flex-shrink:0;width:18px;height:18px;border:2px solid var(--mrd-color-neutral-300);border-top-color:var(--mrd-color-primary);border-radius:50%;animation:mrd-file-spin 0.6s linear infinite}@keyframes mrd-file-spin{to{transform:rotate(360deg)}}.mrd-file-field__error.sc-mrd-file-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}`;
2140
+ /**
2141
+ * Shared upload behaviour for mrd-file-field and mrd-image-field:
2142
+ * file validation, drop-zone class building and drag-drop wiring.
2143
+ */
2144
+ /** Validates a selected/dropped file; returns a localised error message or '' when accepted. */
2145
+ function validateUploadFile(file, maxSize, locale, requireImage = false) {
2146
+ if (maxSize > 0 && file.size > maxSize)
2147
+ return t('file_too_large', locale);
2148
+ if (requireImage && !file.type.startsWith('image/'))
2149
+ return t('invalid_image', locale);
2150
+ return '';
2151
+ }
2152
+ /** BEM class string for the drop zone, e.g. base 'mrd-file-field' → 'mrd-file-field__zone …'. */
2153
+ function uploadZoneClass(base, opts) {
2154
+ return [
2155
+ `${base}__zone`,
2156
+ opts.dragging ? `${base}__zone--dragging` : '',
2157
+ opts.error ? `${base}__zone--error` : '',
2158
+ opts.disabled ? `${base}__zone--disabled` : '',
2159
+ ].filter(Boolean).join(' ');
2160
+ }
2161
+ /** Drag-drop handlers for the drop zone; the component owns the dragging state and file handling. */
2162
+ function makeDragHandlers(setDragging, onFile) {
2163
+ return {
2164
+ onDragOver: (e) => {
2165
+ e.preventDefault();
2166
+ setDragging(true);
2167
+ },
2168
+ onDragLeave: () => setDragging(false),
2169
+ onDrop: (e) => {
2170
+ var _a, _b, _c;
2171
+ e.preventDefault();
2172
+ setDragging(false);
2173
+ onFile((_c = (_b = (_a = e.dataTransfer) === null || _a === void 0 ? void 0 : _a.files) === null || _b === void 0 ? void 0 : _b[0]) !== null && _c !== void 0 ? _c : null);
2174
+ },
2175
+ };
2176
+ }
2177
+
2178
+ const mrdFileFieldCss = () => `.sc-mrd-file-field-h{display:block}.mrd-file-field.sc-mrd-file-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-file-field__label.sc-mrd-file-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-file-field__label--required.sc-mrd-file-field::after{content:" *";color:var(--mrd-color-danger)}.mrd-file-field__error.sc-mrd-file-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}.mrd-file-field__zone.sc-mrd-file-field{display:flex;align-items:center;justify-content:center;border:2px dashed var(--mrd-border-color);border-radius:var(--mrd-border-radius-md);background-color:var(--mrd-color-neutral-50);cursor:pointer;transition:border-color var(--mrd-transition), background-color var(--mrd-transition);min-height:100px;position:relative}.mrd-file-field__zone.sc-mrd-file-field:hover,.mrd-file-field__zone--dragging.sc-mrd-file-field{border-color:var(--mrd-color-primary);background-color:var(--mrd-color-primary-light)}.mrd-file-field__zone--error.sc-mrd-file-field{border-color:var(--mrd-border-color-error)}.mrd-file-field__zone--disabled.sc-mrd-file-field{opacity:0.6;cursor:not-allowed}.mrd-file-field__zone--disabled.sc-mrd-file-field:hover{border-color:var(--mrd-border-color);background-color:var(--mrd-color-neutral-50)}.mrd-file-field__zone.sc-mrd-file-field{padding:var(--mrd-space-6)}.mrd-file-field__input.sc-mrd-file-field{position:absolute;inset:0;opacity:0;width:100%;height:100%;pointer-events:none;cursor:pointer}.mrd-file-field__prompt.sc-mrd-file-field{display:flex;flex-direction:column;align-items:center;gap:var(--mrd-space-2);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-500);text-align:center}.mrd-file-field__upload-icon.sc-mrd-file-field{width:32px;height:32px;color:var(--mrd-color-neutral-400)}.mrd-file-field__browse.sc-mrd-file-field{color:var(--mrd-color-primary);font-weight:var(--mrd-font-weight-medium);text-decoration:underline}.mrd-file-field__selected.sc-mrd-file-field{display:flex;align-items:center;gap:var(--mrd-space-2);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-700)}.mrd-file-field__icon.sc-mrd-file-field{width:20px;height:20px;color:var(--mrd-color-primary);flex-shrink:0}.mrd-file-field__filename.sc-mrd-file-field{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:200px}.mrd-file-field__clear.sc-mrd-file-field{background:none;border:none;cursor:pointer;color:var(--mrd-color-neutral-400);font-size:var(--mrd-font-size-sm);padding:var(--mrd-space-1);border-radius:var(--mrd-border-radius-sm);line-height:1}.mrd-file-field__clear.sc-mrd-file-field:hover{color:var(--mrd-color-danger);background-color:var(--mrd-color-danger-light)}.mrd-file-field__spinner.sc-mrd-file-field{display:inline-block;width:18px;height:18px;border:2px solid var(--mrd-color-neutral-300);border-top-color:var(--mrd-color-primary);border-radius:50%;animation:mrd-spin 0.6s linear infinite;flex-shrink:0}@keyframes mrd-spin{to{transform:rotate(360deg)}}`;
2005
2179
 
2006
2180
  const MrdFileField = class {
2007
2181
  constructor(hostRef) {
@@ -2026,20 +2200,7 @@ const MrdFileField = class {
2026
2200
  const files = e.target.files;
2027
2201
  this.handleFile((_a = files === null || files === void 0 ? void 0 : files[0]) !== null && _a !== void 0 ? _a : null);
2028
2202
  };
2029
- this.handleDragOver = (e) => {
2030
- e.preventDefault();
2031
- this.isDragging = true;
2032
- };
2033
- this.handleDragLeave = () => {
2034
- this.isDragging = false;
2035
- };
2036
- this.handleDrop = (e) => {
2037
- var _a, _b, _c;
2038
- e.preventDefault();
2039
- this.isDragging = false;
2040
- const file = (_c = (_b = (_a = e.dataTransfer) === null || _a === void 0 ? void 0 : _a.files) === null || _b === void 0 ? void 0 : _b[0]) !== null && _c !== void 0 ? _c : null;
2041
- this.handleFile(file);
2042
- };
2203
+ this.drag = makeDragHandlers(dragging => (this.isDragging = dragging), file => this.handleFile(file));
2043
2204
  this.handleZoneClick = () => {
2044
2205
  var _a;
2045
2206
  if (!this.disabled && !this.uploading) {
@@ -2073,8 +2234,9 @@ const MrdFileField = class {
2073
2234
  this.mrdChange.emit({ name: this.name, value: null });
2074
2235
  return;
2075
2236
  }
2076
- if (this.maxSize > 0 && file.size > this.maxSize) {
2077
- this.error = t('file_too_large', this.locale);
2237
+ const uploadError = validateUploadFile(file, this.maxSize, this.locale);
2238
+ if (uploadError) {
2239
+ this.error = uploadError;
2078
2240
  return;
2079
2241
  }
2080
2242
  this.error = '';
@@ -2086,13 +2248,12 @@ const MrdFileField = class {
2086
2248
  render() {
2087
2249
  const hasFile = this.uploading || (typeof this.value === 'string' && this.value) || this.fileName;
2088
2250
  const hasError = !!this.error;
2089
- const zoneClass = [
2090
- 'mrd-file-field__zone',
2091
- this.isDragging ? 'mrd-file-field__zone--dragging' : '',
2092
- hasError ? 'mrd-file-field__zone--error' : '',
2093
- this.disabled || this.uploading ? 'mrd-file-field__zone--disabled' : '',
2094
- ].filter(Boolean).join(' ');
2095
- return (index.h(index.Host, { key: '095bb39f3cb1680cf5e7e51bdfd06d8eb087f237' }, index.h("div", { key: '7e5b5fe6e63b6530221083c8bcb82bcac59a5fe7', class: "mrd-file-field" }, this.label && (index.h("label", { key: 'c34723f4199371d6fe8ea87463d878b89c038590', class: `mrd-file-field__label${this.required ? ' mrd-file-field__label--required' : ''}` }, this.label)), index.h("div", { key: '4727667345d3cd4a5c65a431744a09f366943c13', class: zoneClass, onClick: this.handleZoneClick, onDragOver: this.handleDragOver, onDragLeave: this.handleDragLeave, onDrop: this.handleDrop }, index.h("input", { key: '45ed41c0f094dbe269561c8586e473f908cdf4a4', ref: el => (this.fileInputRef = el), class: "mrd-file-field__input", type: "file", name: this.name, accept: this.accept, disabled: this.disabled || this.uploading, required: this.required && !hasFile, onChange: this.handleInputChange }), hasFile ? (index.h("div", { class: "mrd-file-field__selected" }, this.uploading ? (index.h("span", { class: "mrd-file-field__spinner", "aria-label": t('loading', this.locale) })) : (index.h("svg", { class: "mrd-file-field__icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2" }, index.h("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }), index.h("polyline", { points: "14 2 14 8 20 8" }))), index.h("span", { class: "mrd-file-field__filename" }, this.fileName), !this.uploading && (index.h("button", { class: "mrd-file-field__clear", type: "button", onClick: this.handleClear, "aria-label": t('clear', this.locale) }, "\u2715")))) : (index.h("div", { class: "mrd-file-field__prompt" }, index.h("svg", { class: "mrd-file-field__upload-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2" }, index.h("polyline", { points: "16 16 12 12 8 16" }), index.h("line", { x1: "12", y1: "12", x2: "12", y2: "21" }), index.h("path", { d: "M20.39 18.39A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.3" })), index.h("span", null, t('drop_file_here', this.locale), ' ', index.h("span", { class: "mrd-file-field__browse" }, t('browse', this.locale)))))), hasError && index.h("span", { key: '00ce94ead3c32ed63e903cfd9d8480084a308d84', class: "mrd-file-field__error" }, this.error))));
2251
+ const zoneClass = uploadZoneClass('mrd-file-field', {
2252
+ dragging: this.isDragging,
2253
+ error: hasError,
2254
+ disabled: this.disabled || this.uploading,
2255
+ });
2256
+ return (index.h(index.Host, { key: '2c4cee79cd0f95ed3750dfc86007a2b36aa3da15' }, index.h("div", { key: '5b47d0f83e8e38b22bb04409544ec2af580274f1', class: "mrd-file-field" }, index.h(FieldLabel, { key: '47a92d5680670bf750854fa6e7883da54a40baec', base: "mrd-file-field", label: this.label, required: this.required }), index.h("div", { key: '684f6ab39c32635fb5ca966ccab4a061d8682f89', class: zoneClass, onClick: this.handleZoneClick, onDragOver: this.drag.onDragOver, onDragLeave: this.drag.onDragLeave, onDrop: this.drag.onDrop }, index.h("input", { key: 'a47231d8c68280623daf0c5a2e4341417e7a88d0', ref: el => (this.fileInputRef = el), class: "mrd-file-field__input", type: "file", name: this.name, accept: this.accept, disabled: this.disabled || this.uploading, required: this.required && !hasFile, onChange: this.handleInputChange }), hasFile ? (index.h("div", { class: "mrd-file-field__selected" }, this.uploading ? (index.h("span", { class: "mrd-file-field__spinner", "aria-label": t('loading', this.locale) })) : (index.h("svg", { class: "mrd-file-field__icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2" }, index.h("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }), index.h("polyline", { points: "14 2 14 8 20 8" }))), index.h("span", { class: "mrd-file-field__filename" }, this.fileName), !this.uploading && (index.h("button", { class: "mrd-file-field__clear", type: "button", onClick: this.handleClear, "aria-label": t('clear', this.locale) }, "\u2715")))) : (index.h("div", { class: "mrd-file-field__prompt" }, index.h("svg", { class: "mrd-file-field__upload-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2" }, index.h("polyline", { points: "16 16 12 12 8 16" }), index.h("line", { x1: "12", y1: "12", x2: "12", y2: "21" }), index.h("path", { d: "M20.39 18.39A5 5 0 0 0 18 9h-1.26A8 8 0 1 0 3 16.3" })), index.h("span", null, t('drop_file_here', this.locale), ' ', index.h("span", { class: "mrd-file-field__browse" }, t('browse', this.locale)))))), index.h(FieldError, { key: '5f18e91aa94319a5571c368e745c108fb0d371a7', base: "mrd-file-field", error: this.error }))));
2096
2257
  }
2097
2258
  static get watchers() { return {
2098
2259
  "value": [{
@@ -2100,9 +2261,9 @@ const MrdFileField = class {
2100
2261
  }]
2101
2262
  }; }
2102
2263
  };
2103
- MrdFileField.style = mrdFileFieldScss();
2264
+ MrdFileField.style = mrdFileFieldCss();
2104
2265
 
2105
- const mrdFormScss = () => `.sc-mrd-form-h{display:block}.mrd-form.sc-mrd-form{font-family:var(--mrd-font-family);width:100%}.mrd-form__title.sc-mrd-form{font-size:var(--mrd-font-size-2xl);font-weight:var(--mrd-font-weight-bold);color:var(--mrd-color-neutral-900);margin:0 0 var(--mrd-space-6) 0}.mrd-form__body.sc-mrd-form{display:flex;flex-direction:column;gap:var(--mrd-space-5)}.mrd-form__field.sc-mrd-form{display:flex;flex-direction:column;gap:var(--mrd-space-1)}.mrd-form__field-error.sc-mrd-form{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}.mrd-form__section.sc-mrd-form{border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius-md);padding:var(--mrd-space-4) var(--mrd-space-5);margin:0}.mrd-form__section-legend.sc-mrd-form{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);font-weight:var(--mrd-font-weight-semibold);color:var(--mrd-color-neutral-700);padding:0 var(--mrd-space-2)}.mrd-form__section-body.sc-mrd-form{display:flex;flex-direction:column;gap:var(--mrd-space-4);margin-top:var(--mrd-space-2)}.mrd-form__group.sc-mrd-form{display:flex;flex-direction:column;gap:var(--mrd-space-2)}.mrd-form__group-label.sc-mrd-form{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-semibold);color:var(--mrd-color-neutral-500);text-transform:uppercase;letter-spacing:0.05em}.mrd-form__group-body.sc-mrd-form{display:flex;flex-direction:column;gap:var(--mrd-space-4);padding-left:var(--mrd-space-4);border-left:3px solid var(--mrd-color-neutral-200)}.mrd-form__footer.sc-mrd-form{margin-top:var(--mrd-space-8);padding-top:var(--mrd-space-5);border-top:var(--mrd-border-width) solid var(--mrd-border-color);display:flex;justify-content:flex-end;gap:var(--mrd-space-3)}.mrd-form__submit.sc-mrd-form{display:inline-flex;align-items:center;justify-content:center;height:var(--mrd-input-height);padding:0 var(--mrd-space-6);background-color:var(--mrd-color-primary);color:var(--mrd-color-white);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);font-weight:var(--mrd-font-weight-medium);border:none;border-radius:var(--mrd-border-radius);cursor:pointer;transition:background-color var(--mrd-transition)}.mrd-form__submit.sc-mrd-form:hover{background-color:var(--mrd-color-primary-hover)}.mrd-form__submit.sc-mrd-form:focus{outline:none;box-shadow:var(--mrd-shadow-focus)}.mrd-form__submit.sc-mrd-form:active{background-color:var(--mrd-color-primary-dark)}.mrd-form__cancel.sc-mrd-form{display:inline-flex;align-items:center;justify-content:center;height:var(--mrd-input-height);padding:0 var(--mrd-space-6);background-color:transparent;color:var(--mrd-color-neutral-600);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);font-weight:var(--mrd-font-weight-medium);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);cursor:pointer;transition:background-color var(--mrd-transition), color var(--mrd-transition)}.mrd-form__cancel.sc-mrd-form:hover{background-color:var(--mrd-color-neutral-100);color:var(--mrd-color-neutral-800)}.mrd-form__cancel.sc-mrd-form:focus{outline:none;box-shadow:var(--mrd-shadow-focus)}.mrd-form__cancel.sc-mrd-form:active{background-color:var(--mrd-color-neutral-200)}`;
2266
+ const mrdFormCss = () => `.sc-mrd-form-h{display:block}.mrd-form.sc-mrd-form{font-family:var(--mrd-font-family);width:100%}.mrd-form__title.sc-mrd-form{font-size:var(--mrd-font-size-2xl);font-weight:var(--mrd-font-weight-bold);color:var(--mrd-color-neutral-900);margin:0 0 var(--mrd-space-6) 0}.mrd-form__body.sc-mrd-form{display:flex;flex-direction:column;gap:var(--mrd-space-5)}.mrd-form__field.sc-mrd-form{display:flex;flex-direction:column;gap:var(--mrd-space-1)}.mrd-form__field-error.sc-mrd-form{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}.mrd-form__section.sc-mrd-form{border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius-md);padding:var(--mrd-space-4) var(--mrd-space-5);margin:0}.mrd-form__section-legend.sc-mrd-form{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);font-weight:var(--mrd-font-weight-semibold);color:var(--mrd-color-neutral-700);padding:0 var(--mrd-space-2)}.mrd-form__section-body.sc-mrd-form{display:flex;flex-direction:column;gap:var(--mrd-space-4);margin-top:var(--mrd-space-2)}.mrd-form__group.sc-mrd-form{display:flex;flex-direction:column;gap:var(--mrd-space-2)}.mrd-form__group-label.sc-mrd-form{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-semibold);color:var(--mrd-color-neutral-500);text-transform:uppercase;letter-spacing:0.05em}.mrd-form__group-body.sc-mrd-form{display:flex;flex-direction:column;gap:var(--mrd-space-4);padding-left:var(--mrd-space-4);border-left:3px solid var(--mrd-color-neutral-200)}.mrd-form__footer.sc-mrd-form{margin-top:var(--mrd-space-8);padding-top:var(--mrd-space-5);border-top:var(--mrd-border-width) solid var(--mrd-border-color);display:flex;justify-content:flex-end;gap:var(--mrd-space-3)}.mrd-form__submit.sc-mrd-form{display:inline-flex;align-items:center;justify-content:center;height:var(--mrd-input-height);padding:0 var(--mrd-space-6);background-color:var(--mrd-color-primary);color:var(--mrd-color-white);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);font-weight:var(--mrd-font-weight-medium);border:none;border-radius:var(--mrd-border-radius);cursor:pointer;transition:background-color var(--mrd-transition)}.mrd-form__submit.sc-mrd-form:hover{background-color:var(--mrd-color-primary-hover)}.mrd-form__submit.sc-mrd-form:focus{outline:none;box-shadow:var(--mrd-shadow-focus)}.mrd-form__submit.sc-mrd-form:active{background-color:var(--mrd-color-primary-dark)}.mrd-form__cancel.sc-mrd-form{display:inline-flex;align-items:center;justify-content:center;height:var(--mrd-input-height);padding:0 var(--mrd-space-6);background-color:transparent;color:var(--mrd-color-neutral-600);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);font-weight:var(--mrd-font-weight-medium);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);cursor:pointer;transition:background-color var(--mrd-transition), color var(--mrd-transition)}.mrd-form__cancel.sc-mrd-form:hover{background-color:var(--mrd-color-neutral-100);color:var(--mrd-color-neutral-800)}.mrd-form__cancel.sc-mrd-form:focus{outline:none;box-shadow:var(--mrd-shadow-focus)}.mrd-form__cancel.sc-mrd-form:active{background-color:var(--mrd-color-neutral-200)}`;
2106
2267
 
2107
2268
  const MrdForm = class {
2108
2269
  constructor(hostRef) {
@@ -2469,9 +2630,9 @@ const MrdForm = class {
2469
2630
  }]
2470
2631
  }; }
2471
2632
  };
2472
- MrdForm.style = mrdFormScss();
2633
+ MrdForm.style = mrdFormCss();
2473
2634
 
2474
- const mrdHyperlinkFieldScss = () => `.sc-mrd-hyperlink-field-h{display:block}.mrd-hyperlink-field.sc-mrd-hyperlink-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-hyperlink-field__label.sc-mrd-hyperlink-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-hyperlink-field__label--required.sc-mrd-hyperlink-field::after{content:' *';color:var(--mrd-color-danger)}.mrd-hyperlink-field__input.sc-mrd-hyperlink-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box}.mrd-hyperlink-field__input.sc-mrd-hyperlink-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-hyperlink-field__input.sc-mrd-hyperlink-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-hyperlink-field__input.sc-mrd-hyperlink-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-hyperlink-field__input--error.sc-mrd-hyperlink-field{border-color:var(--mrd-border-color-error)}.mrd-hyperlink-field__input--error.sc-mrd-hyperlink-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-hyperlink-field__input--name.sc-mrd-hyperlink-field{margin-top:var(--mrd-space-1)}.mrd-hyperlink-field__link.sc-mrd-hyperlink-field{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-color-primary);text-decoration:underline;word-break:break-all}.mrd-hyperlink-field__link.sc-mrd-hyperlink-field:hover{opacity:0.8}.mrd-hyperlink-field__empty.sc-mrd-hyperlink-field{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-color-neutral-400)}.mrd-hyperlink-field__error.sc-mrd-hyperlink-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}`;
2635
+ const mrdHyperlinkFieldCss = () => `.sc-mrd-hyperlink-field-h{display:block}.mrd-hyperlink-field.sc-mrd-hyperlink-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-hyperlink-field__label.sc-mrd-hyperlink-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-hyperlink-field__label--required.sc-mrd-hyperlink-field::after{content:" *";color:var(--mrd-color-danger)}.mrd-hyperlink-field__input.sc-mrd-hyperlink-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box}.mrd-hyperlink-field__input.sc-mrd-hyperlink-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-hyperlink-field__input.sc-mrd-hyperlink-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-hyperlink-field__input.sc-mrd-hyperlink-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-hyperlink-field__input--error.sc-mrd-hyperlink-field{border-color:var(--mrd-border-color-error)}.mrd-hyperlink-field__input--error.sc-mrd-hyperlink-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-hyperlink-field__error.sc-mrd-hyperlink-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}.mrd-hyperlink-field__input--name.sc-mrd-hyperlink-field{margin-top:var(--mrd-space-1)}.mrd-hyperlink-field__link.sc-mrd-hyperlink-field{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-color-primary);text-decoration:underline;word-break:break-all}.mrd-hyperlink-field__link.sc-mrd-hyperlink-field:hover{opacity:0.8}.mrd-hyperlink-field__empty.sc-mrd-hyperlink-field{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-color-neutral-400)}`;
2475
2636
 
2476
2637
  const MrdHyperlinkField = class {
2477
2638
  constructor(hostRef) {
@@ -2497,15 +2658,8 @@ const MrdHyperlinkField = class {
2497
2658
  this.mrdChange.emit({ name: this.name, value: this.buildValue() });
2498
2659
  };
2499
2660
  this.handleBlur = () => {
2500
- if (this.required && !validateRequired(this.internalHref)) {
2501
- this.error = t('required', this.locale);
2502
- }
2503
- else if (this.internalHref && !validateUrl(this.internalHref)) {
2504
- this.error = t('invalid_url', this.locale);
2505
- }
2506
- else {
2507
- this.error = '';
2508
- }
2661
+ this.error = requiredError(this.internalHref, this.required, this.locale)
2662
+ || (this.internalHref && !validateUrl(this.internalHref) ? t('invalid_url', this.locale) : '');
2509
2663
  this.mrdBlur.emit({ name: this.name, value: this.buildValue() });
2510
2664
  };
2511
2665
  }
@@ -2538,7 +2692,7 @@ const MrdHyperlinkField = class {
2538
2692
  ? index.h("a", { class: "mrd-hyperlink-field__link", href: this.internalHref, target: "_blank", rel: "noopener noreferrer" }, this.internalName || this.internalHref)
2539
2693
  : index.h("span", { class: "mrd-hyperlink-field__empty" }, "\u2014"))));
2540
2694
  }
2541
- return (index.h(index.Host, null, index.h("div", { class: "mrd-hyperlink-field" }, this.label && (index.h("label", { class: `mrd-hyperlink-field__label${this.required ? ' mrd-hyperlink-field__label--required' : ''}` }, this.label)), index.h("input", { class: `mrd-hyperlink-field__input${hasError ? ' mrd-hyperlink-field__input--error' : ''}`, type: "url", name: this.name, value: this.internalHref, placeholder: this.placeholder || 'https://', required: this.required, onInput: this.handleHrefInput, onBlur: this.handleBlur }), index.h("input", { class: "mrd-hyperlink-field__input mrd-hyperlink-field__input--name", type: "text", value: this.internalName, placeholder: t('hyperlink_name', this.locale), onInput: this.handleNameInput, onBlur: this.handleBlur }), hasError && index.h("span", { class: "mrd-hyperlink-field__error" }, this.error))));
2695
+ return (index.h(index.Host, null, index.h("div", { class: "mrd-hyperlink-field" }, index.h(FieldLabel, { base: "mrd-hyperlink-field", label: this.label, required: this.required }), index.h("input", { class: controlClass('mrd-hyperlink-field', hasError), type: "url", name: this.name, value: this.internalHref, placeholder: this.placeholder || 'https://', required: this.required, onInput: this.handleHrefInput, onBlur: this.handleBlur }), index.h("input", { class: "mrd-hyperlink-field__input mrd-hyperlink-field__input--name", type: "text", value: this.internalName, placeholder: t('hyperlink_name', this.locale), onInput: this.handleNameInput, onBlur: this.handleBlur }), index.h(FieldError, { base: "mrd-hyperlink-field", error: this.error }))));
2542
2696
  }
2543
2697
  static get watchers() { return {
2544
2698
  "value": [{
@@ -2546,9 +2700,9 @@ const MrdHyperlinkField = class {
2546
2700
  }]
2547
2701
  }; }
2548
2702
  };
2549
- MrdHyperlinkField.style = mrdHyperlinkFieldScss();
2703
+ MrdHyperlinkField.style = mrdHyperlinkFieldCss();
2550
2704
 
2551
- const mrdImageFieldScss = () => `.sc-mrd-image-field-h{display:block}.mrd-image-field.sc-mrd-image-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-image-field__label.sc-mrd-image-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-image-field__label--required.sc-mrd-image-field::after{content:' *';color:var(--mrd-color-danger)}.mrd-image-field__zone.sc-mrd-image-field{display:flex;align-items:center;justify-content:center;border:2px dashed var(--mrd-border-color);border-radius:var(--mrd-border-radius-md);background-color:var(--mrd-color-neutral-50);cursor:pointer;transition:border-color var(--mrd-transition), background-color var(--mrd-transition);min-height:100px;position:relative}.mrd-image-field__zone.sc-mrd-image-field:hover{border-color:var(--mrd-color-primary);background-color:var(--mrd-color-primary-light)}.mrd-image-field__zone--dragging.sc-mrd-image-field{border-color:var(--mrd-color-primary);background-color:var(--mrd-color-primary-light)}.mrd-image-field__zone--error.sc-mrd-image-field{border-color:var(--mrd-border-color-error)}.mrd-image-field__zone--disabled.sc-mrd-image-field{opacity:0.6;cursor:not-allowed}.mrd-image-field__zone--disabled.sc-mrd-image-field:hover{border-color:var(--mrd-border-color);background-color:var(--mrd-color-neutral-50)}.mrd-image-field__input.sc-mrd-image-field{position:absolute;inset:0;opacity:0;width:100%;height:100%;pointer-events:none}.mrd-image-field__prompt.sc-mrd-image-field{display:flex;flex-direction:column;align-items:center;gap:var(--mrd-space-2);padding:var(--mrd-space-6);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-500);text-align:center}.mrd-image-field__upload-icon.sc-mrd-image-field{width:40px;height:40px;color:var(--mrd-color-neutral-400)}.mrd-image-field__browse.sc-mrd-image-field{color:var(--mrd-color-primary);font-weight:var(--mrd-font-weight-medium);text-decoration:underline}.mrd-image-field__preview-container.sc-mrd-image-field{display:flex;align-items:center;gap:var(--mrd-space-4);padding:var(--mrd-space-4);width:100%}.mrd-image-field__preview-thumb.sc-mrd-image-field{flex-shrink:0;width:80px;height:80px;border-radius:var(--mrd-border-radius);overflow:hidden;border:var(--mrd-border-width) solid var(--mrd-border-color);background-color:var(--mrd-color-neutral-100)}.mrd-image-field__preview.sc-mrd-image-field{width:100%;height:100%;object-fit:cover;display:block}.mrd-image-field__preview-info.sc-mrd-image-field{flex:1;min-width:0;display:flex;flex-direction:column;gap:var(--mrd-space-1)}.mrd-image-field__preview-name.sc-mrd-image-field{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-medium);color:var(--mrd-color-neutral-800);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mrd-image-field__preview-overlay.sc-mrd-image-field{position:absolute;inset:0;background:rgb(255 255 255 / 0.7);display:flex;align-items:center;justify-content:center;border-radius:var(--mrd-border-radius)}.mrd-image-field__spinner.sc-mrd-image-field{display:inline-block;width:24px;height:24px;border:2px solid var(--mrd-color-neutral-300);border-top-color:var(--mrd-color-primary);border-radius:50%;animation:mrd-image-spin 0.6s linear infinite}@keyframes mrd-image-spin{to{transform:rotate(360deg)}}.mrd-image-field__upload-status.sc-mrd-image-field{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-500)}.mrd-image-field__clear.sc-mrd-image-field{flex-shrink:0;background-color:var(--mrd-color-white);color:var(--mrd-color-danger);border:var(--mrd-border-width) solid var(--mrd-color-danger);border-radius:var(--mrd-border-radius);padding:var(--mrd-space-1) var(--mrd-space-3);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-medium);cursor:pointer;transition:background-color var(--mrd-transition), color var(--mrd-transition)}.mrd-image-field__clear.sc-mrd-image-field:hover{background-color:var(--mrd-color-danger);color:var(--mrd-color-white)}.mrd-image-field__error.sc-mrd-image-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}`;
2705
+ const mrdImageFieldCss = () => `.sc-mrd-image-field-h{display:block}.mrd-image-field.sc-mrd-image-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-image-field__label.sc-mrd-image-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-image-field__label--required.sc-mrd-image-field::after{content:" *";color:var(--mrd-color-danger)}.mrd-image-field__error.sc-mrd-image-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}.mrd-image-field__zone.sc-mrd-image-field{display:flex;align-items:center;justify-content:center;border:2px dashed var(--mrd-border-color);border-radius:var(--mrd-border-radius-md);background-color:var(--mrd-color-neutral-50);cursor:pointer;transition:border-color var(--mrd-transition), background-color var(--mrd-transition);min-height:100px;position:relative}.mrd-image-field__zone.sc-mrd-image-field:hover,.mrd-image-field__zone--dragging.sc-mrd-image-field{border-color:var(--mrd-color-primary);background-color:var(--mrd-color-primary-light)}.mrd-image-field__zone--error.sc-mrd-image-field{border-color:var(--mrd-border-color-error)}.mrd-image-field__zone--disabled.sc-mrd-image-field{opacity:0.6;cursor:not-allowed}.mrd-image-field__zone--disabled.sc-mrd-image-field:hover{border-color:var(--mrd-border-color);background-color:var(--mrd-color-neutral-50)}.mrd-image-field__input.sc-mrd-image-field{position:absolute;inset:0;opacity:0;width:100%;height:100%;pointer-events:none}.mrd-image-field__prompt.sc-mrd-image-field{display:flex;flex-direction:column;align-items:center;gap:var(--mrd-space-2);padding:var(--mrd-space-6);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-500);text-align:center}.mrd-image-field__upload-icon.sc-mrd-image-field{width:40px;height:40px;color:var(--mrd-color-neutral-400)}.mrd-image-field__browse.sc-mrd-image-field{color:var(--mrd-color-primary);font-weight:var(--mrd-font-weight-medium);text-decoration:underline}.mrd-image-field__preview-container.sc-mrd-image-field{display:flex;align-items:center;gap:var(--mrd-space-4);padding:var(--mrd-space-4);width:100%}.mrd-image-field__preview-thumb.sc-mrd-image-field{flex-shrink:0;width:80px;height:80px;border-radius:var(--mrd-border-radius);overflow:hidden;border:var(--mrd-border-width) solid var(--mrd-border-color);background-color:var(--mrd-color-neutral-100)}.mrd-image-field__preview.sc-mrd-image-field{width:100%;height:100%;object-fit:cover;display:block}.mrd-image-field__preview-info.sc-mrd-image-field{flex:1;min-width:0;display:flex;flex-direction:column;gap:var(--mrd-space-1)}.mrd-image-field__preview-name.sc-mrd-image-field{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-medium);color:var(--mrd-color-neutral-800);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mrd-image-field__preview-overlay.sc-mrd-image-field{position:absolute;inset:0;background:rgba(255, 255, 255, 0.7);display:flex;align-items:center;justify-content:center;border-radius:var(--mrd-border-radius)}.mrd-image-field__spinner.sc-mrd-image-field{display:inline-block;width:24px;height:24px;border:2px solid var(--mrd-color-neutral-300);border-top-color:var(--mrd-color-primary);border-radius:50%;animation:mrd-spin 0.6s linear infinite}@keyframes mrd-spin{to{transform:rotate(360deg)}}.mrd-image-field__upload-status.sc-mrd-image-field{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-500)}.mrd-image-field__clear.sc-mrd-image-field{flex-shrink:0;background-color:var(--mrd-color-white);color:var(--mrd-color-danger);border:var(--mrd-border-width) solid var(--mrd-color-danger);border-radius:var(--mrd-border-radius);padding:var(--mrd-space-1) var(--mrd-space-3);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-medium);cursor:pointer;transition:background-color var(--mrd-transition), color var(--mrd-transition)}.mrd-image-field__clear.sc-mrd-image-field:hover{background-color:var(--mrd-color-danger);color:var(--mrd-color-white)}`;
2552
2706
 
2553
2707
  const MrdImageField = class {
2554
2708
  constructor(hostRef) {
@@ -2574,20 +2728,7 @@ const MrdImageField = class {
2574
2728
  const files = e.target.files;
2575
2729
  this.handleFile((_a = files === null || files === void 0 ? void 0 : files[0]) !== null && _a !== void 0 ? _a : null);
2576
2730
  };
2577
- this.handleDragOver = (e) => {
2578
- e.preventDefault();
2579
- this.isDragging = true;
2580
- };
2581
- this.handleDragLeave = () => {
2582
- this.isDragging = false;
2583
- };
2584
- this.handleDrop = (e) => {
2585
- var _a, _b, _c;
2586
- e.preventDefault();
2587
- this.isDragging = false;
2588
- const file = (_c = (_b = (_a = e.dataTransfer) === null || _a === void 0 ? void 0 : _a.files) === null || _b === void 0 ? void 0 : _b[0]) !== null && _c !== void 0 ? _c : null;
2589
- this.handleFile(file);
2590
- };
2731
+ this.drag = makeDragHandlers(dragging => (this.isDragging = dragging), file => this.handleFile(file));
2591
2732
  this.handleZoneClick = () => {
2592
2733
  var _a;
2593
2734
  if (!this.disabled && !this.uploading) {
@@ -2624,12 +2765,9 @@ const MrdImageField = class {
2624
2765
  this.mrdChange.emit({ name: this.name, value: null });
2625
2766
  return;
2626
2767
  }
2627
- if (this.maxSize > 0 && file.size > this.maxSize) {
2628
- this.error = t('file_too_large', this.locale);
2629
- return;
2630
- }
2631
- if (!file.type.startsWith('image/')) {
2632
- this.error = 'Please select an image file';
2768
+ const uploadError = validateUploadFile(file, this.maxSize, this.locale, true);
2769
+ if (uploadError) {
2770
+ this.error = uploadError;
2633
2771
  return;
2634
2772
  }
2635
2773
  this.error = '';
@@ -2647,13 +2785,12 @@ const MrdImageField = class {
2647
2785
  }
2648
2786
  render() {
2649
2787
  const hasError = !!this.error;
2650
- const zoneClass = [
2651
- 'mrd-image-field__zone',
2652
- this.isDragging ? 'mrd-image-field__zone--dragging' : '',
2653
- hasError ? 'mrd-image-field__zone--error' : '',
2654
- this.disabled || this.uploading ? 'mrd-image-field__zone--disabled' : '',
2655
- ].filter(Boolean).join(' ');
2656
- return (index.h(index.Host, { key: '97db2df72839f36b7a46e153a5dd1c208c52b522' }, index.h("div", { key: 'c8f2d3d858f90d322d26082aaf5adb57acfc78f4', class: "mrd-image-field" }, this.label && (index.h("label", { key: '6625e5031ff0b7c06f76c1ea0387f1bd5c1858a4', class: `mrd-image-field__label${this.required ? ' mrd-image-field__label--required' : ''}` }, this.label)), index.h("div", { key: '364216e6a96e845e21c42e821fdff02bd2612ff8', class: zoneClass, onClick: this.handleZoneClick, onDragOver: this.handleDragOver, onDragLeave: this.handleDragLeave, onDrop: this.handleDrop }, index.h("input", { key: '0487706ddd9f48cda1cb0c2a178809d90674486b', ref: el => (this.fileInputRef = el), class: "mrd-image-field__input", type: "file", name: this.name, accept: this.accept, disabled: this.disabled || this.uploading, required: this.required && !this.previewUrl, onChange: this.handleInputChange }), this.previewUrl ? (index.h("div", { class: "mrd-image-field__preview-container" }, index.h("div", { class: "mrd-image-field__preview-thumb" }, index.h("img", { class: "mrd-image-field__preview", src: this.previewUrl, alt: this.fileName }), this.uploading && index.h("div", { class: "mrd-image-field__preview-overlay" }, index.h("span", { class: "mrd-image-field__spinner" }))), index.h("div", { class: "mrd-image-field__preview-info" }, index.h("span", { class: "mrd-image-field__preview-name" }, this.fileName), this.uploading && (index.h("span", { class: "mrd-image-field__upload-status" }, t('loading', this.locale)))), !this.uploading && (index.h("button", { class: "mrd-image-field__clear", type: "button", onClick: this.handleClear, "aria-label": t('clear', this.locale) }, t('remove', this.locale))))) : (index.h("div", { class: "mrd-image-field__prompt" }, index.h("svg", { class: "mrd-image-field__upload-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2" }, index.h("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }), index.h("circle", { cx: "8.5", cy: "8.5", r: "1.5" }), index.h("polyline", { points: "21 15 16 10 5 21" })), index.h("span", null, t('drop_file_here', this.locale), ' ', index.h("span", { class: "mrd-image-field__browse" }, t('browse', this.locale)))))), hasError && index.h("span", { key: 'bd505ef4f4b67c4e9138d8825c6e600f583f4cab', class: "mrd-image-field__error" }, this.error))));
2788
+ const zoneClass = uploadZoneClass('mrd-image-field', {
2789
+ dragging: this.isDragging,
2790
+ error: hasError,
2791
+ disabled: this.disabled || this.uploading,
2792
+ });
2793
+ return (index.h(index.Host, { key: 'ab78d93ab6c810363a8993bea4545f7406680e58' }, index.h("div", { key: '727ae5d9c1cce22d90d26229a9ea5d677abb4b07', class: "mrd-image-field" }, index.h(FieldLabel, { key: 'aab0e9fcc0204e8ea617453b5ca458f683194125', base: "mrd-image-field", label: this.label, required: this.required }), index.h("div", { key: '1241faff26c47a303fd0431201f490c6b8725987', class: zoneClass, onClick: this.handleZoneClick, onDragOver: this.drag.onDragOver, onDragLeave: this.drag.onDragLeave, onDrop: this.drag.onDrop }, index.h("input", { key: '70e3b8f869927ad525465ace96ed3ea24f5b7555', ref: el => (this.fileInputRef = el), class: "mrd-image-field__input", type: "file", name: this.name, accept: this.accept, disabled: this.disabled || this.uploading, required: this.required && !this.previewUrl, onChange: this.handleInputChange }), this.previewUrl ? (index.h("div", { class: "mrd-image-field__preview-container" }, index.h("div", { class: "mrd-image-field__preview-thumb" }, index.h("img", { class: "mrd-image-field__preview", src: this.previewUrl, alt: this.fileName }), this.uploading && index.h("div", { class: "mrd-image-field__preview-overlay" }, index.h("span", { class: "mrd-image-field__spinner" }))), index.h("div", { class: "mrd-image-field__preview-info" }, index.h("span", { class: "mrd-image-field__preview-name" }, this.fileName), this.uploading && (index.h("span", { class: "mrd-image-field__upload-status" }, t('loading', this.locale)))), !this.uploading && (index.h("button", { class: "mrd-image-field__clear", type: "button", onClick: this.handleClear, "aria-label": t('clear', this.locale) }, t('remove', this.locale))))) : (index.h("div", { class: "mrd-image-field__prompt" }, index.h("svg", { class: "mrd-image-field__upload-icon", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2" }, index.h("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }), index.h("circle", { cx: "8.5", cy: "8.5", r: "1.5" }), index.h("polyline", { points: "21 15 16 10 5 21" })), index.h("span", null, t('drop_file_here', this.locale), ' ', index.h("span", { class: "mrd-image-field__browse" }, t('browse', this.locale)))))), index.h(FieldError, { key: '01552a994c1e5a9f25129586a95562c32a377046', base: "mrd-image-field", error: this.error }))));
2657
2794
  }
2658
2795
  static get watchers() { return {
2659
2796
  "value": [{
@@ -2661,7 +2798,36 @@ const MrdImageField = class {
2661
2798
  }]
2662
2799
  }; }
2663
2800
  };
2664
- MrdImageField.style = mrdImageFieldScss();
2801
+ MrdImageField.style = mrdImageFieldCss();
2802
+
2803
+ /** Key an embedded view is addressed by (setViewPage etc.). */
2804
+ function viewKeyFor(item) {
2805
+ var _a, _b, _c, _d;
2806
+ if (item.type === index$1.ClientLayoutItemType.RELATED_VIEW)
2807
+ return (_b = (_a = item.relatedClass) !== null && _a !== void 0 ? _a : item.name) !== null && _b !== void 0 ? _b : '';
2808
+ return (_d = (_c = item.dataClass) !== null && _c !== void 0 ? _c : item.name) !== null && _d !== void 0 ? _d : '';
2809
+ }
2810
+ /** Depth-first flatten of the SECTION/GROUP tree. */
2811
+ function flattenItems(items) {
2812
+ const result = [];
2813
+ for (const item of items) {
2814
+ result.push(item);
2815
+ if (item.items)
2816
+ result.push(...flattenItems(item.items));
2817
+ }
2818
+ return result;
2819
+ }
2820
+ /** Build the canonical parent href `/{base}/{tenant}/{fromClass}/{parentId}` from
2821
+ * the object's self href. Empty unless it is a RELATED_VIEW with a fromClass. */
2822
+ function buildContainerHref(item, selfHref, parentId) {
2823
+ if (item.type !== index$1.ClientLayoutItemType.RELATED_VIEW || !item.fromClass || !parentId)
2824
+ return '';
2825
+ const segs = selfHref.split('/').filter(Boolean);
2826
+ if (segs.length < 2)
2827
+ return '';
2828
+ const [base, tenant] = segs;
2829
+ return `/${base}/${tenant}/${item.fromClass}/${parentId}`;
2830
+ }
2665
2831
 
2666
2832
  class CellRenderer {
2667
2833
  static render(column, row, locale) {
@@ -2767,7 +2933,114 @@ class CellRenderer {
2767
2933
  }
2768
2934
  }
2769
2935
 
2770
- const mrdLayoutSectionScss = () => `.mrd-layout-section.sc-mrd-layout-section{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-color-neutral-800)}.mrd-layout-section__field.sc-mrd-layout-section{display:grid;grid-template-columns:200px 1fr;align-items:baseline;gap:0 var(--mrd-space-2);padding:var(--mrd-space-1) 0}.mrd-layout-section__field-label.sc-mrd-layout-section{font-size:var(--mrd-font-size-xs);font-weight:var(--mrd-font-weight-normal);color:var(--mrd-color-neutral-500);padding-top:1px}.mrd-layout-section__field-value.sc-mrd-layout-section{font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-medium);color:var(--mrd-color-neutral-800);word-break:break-word;display:inline-flex;align-items:center;gap:var(--mrd-space-1)}.mrd-layout-section__history-wrap.sc-mrd-layout-section{position:relative;display:inline-flex;align-items:center}.mrd-layout-section__history-btn.sc-mrd-layout-section{display:inline-flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;padding:0;background:transparent;border:none;border-radius:var(--mrd-border-radius-sm);color:var(--mrd-color-neutral-400);cursor:pointer;flex-shrink:0;transition:color var(--mrd-transition-fast), background-color var(--mrd-transition-fast)}.mrd-layout-section__history-btn.sc-mrd-layout-section:hover{color:var(--mrd-color-neutral-700);background-color:var(--mrd-color-neutral-100)}.mrd-layout-section__history-btn.sc-mrd-layout-section:focus{outline:none;box-shadow:var(--mrd-shadow-focus)}.mrd-layout-section__history-icon.sc-mrd-layout-section{width:0.875rem;height:0.875rem}.mrd-layout-section__history-popover.sc-mrd-layout-section{position:absolute;top:calc(100% + 0.25rem);left:0;min-width:24rem;max-width:24rem;background-color:var(--mrd-color-white);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius-md);box-shadow:var(--mrd-shadow-md);padding:var(--mrd-space-1) 0;z-index:var(--mrd-z-dropdown)}.mrd-layout-section__history-entry.sc-mrd-layout-section{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-normal);color:var(--mrd-color-neutral-700);padding:var(--mrd-space-2) var(--mrd-space-3);line-height:var(--mrd-line-height-normal)}.mrd-layout-section__history-entry.sc-mrd-layout-section:not(:last-child){border-bottom:var(--mrd-border-width) solid var(--mrd-color-neutral-100)}.mrd-layout-section__field-header.sc-mrd-layout-section{font-size:var(--mrd-font-size-2xl);font-weight:var(--mrd-font-weight-bold);color:var(--mrd-color-neutral-900);margin:0 0 var(--mrd-space-4) 0;padding:0}.mrd-layout-section__header.sc-mrd-layout-section{font-size:var(--mrd-font-size-xl);font-weight:var(--mrd-font-weight-semibold);color:var(--mrd-color-neutral-800);margin:var(--mrd-space-4) 0 var(--mrd-space-2) 0;padding:0}.mrd-layout-section__text.sc-mrd-layout-section{font-size:var(--mrd-font-size-base);color:var(--mrd-color-neutral-700);line-height:var(--mrd-line-height-relaxed);margin:var(--mrd-space-2) 0}.mrd-layout-section__navigate.sc-mrd-layout-section{display:inline-flex;align-items:center;gap:var(--mrd-space-2);padding:var(--mrd-space-2) var(--mrd-space-3);background:none;border:1px solid var(--mrd-color-neutral-300);border-radius:var(--mrd-border-radius);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-primary);cursor:pointer;margin:var(--mrd-space-2) 0}.mrd-layout-section__navigate.sc-mrd-layout-section:hover{background-color:var(--mrd-color-primary-light);border-color:var(--mrd-color-primary)}.mrd-layout-section__link.sc-mrd-layout-section{color:var(--mrd-color-primary);text-decoration:none}.mrd-layout-section__link.sc-mrd-layout-section:hover{text-decoration:underline}.mrd-layout-section__relation-link.sc-mrd-layout-section{background:none;border:none;padding:0;font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-semibold);color:var(--mrd-color-primary);cursor:pointer;text-align:left}.mrd-layout-section__relation-link.sc-mrd-layout-section:hover{text-decoration:underline}.mrd-layout-section__download-link.sc-mrd-layout-section{display:inline-flex;align-items:center;gap:var(--mrd-space-1);background:none;border:none;padding:0;font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-primary);cursor:pointer;text-align:left}.mrd-layout-section__download-link.sc-mrd-layout-section:hover{text-decoration:underline;color:var(--mrd-color-primary-dark)}.mrd-layout-section__file-icon.sc-mrd-layout-section{flex-shrink:0;width:1rem;height:1rem}.mrd-layout-section__boolean--true.sc-mrd-layout-section{color:var(--mrd-color-success);font-weight:var(--mrd-font-weight-semibold)}.mrd-layout-section__boolean--false.sc-mrd-layout-section{color:var(--mrd-color-neutral-400)}.mrd-layout-section__field--block.sc-mrd-layout-section{grid-template-columns:1fr}.mrd-layout-section__badge.sc-mrd-layout-section{display:inline-block;font-size:var(--mrd-font-size-xs);font-weight:var(--mrd-font-weight-medium);padding:2px var(--mrd-space-3);border-radius:10px}.mrd-layout-section__badge-dot-row.sc-mrd-layout-section{display:inline-flex;align-items:center;gap:var(--mrd-space-2)}.mrd-layout-section__badge-dot.sc-mrd-layout-section{display:inline-block;width:10px;height:10px;border-radius:50%;flex-shrink:0}.mrd-layout-section__secret-masked.sc-mrd-layout-section{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-label-color);letter-spacing:0.15em;user-select:none;pointer-events:none}.mrd-layout-section__pre.sc-mrd-layout-section{font-family:var(--mrd-font-family-mono);font-size:var(--mrd-font-size-xs);background-color:var(--mrd-color-neutral-50);border:1px solid var(--mrd-color-neutral-200);border-radius:var(--mrd-border-radius);padding:var(--mrd-space-3);margin:0;max-height:calc(10 * 1.5 * var(--mrd-font-size-xs));overflow-x:auto;overflow-y:auto;white-space:pre-wrap;word-break:break-word}.mrd-layout-section__group.sc-mrd-layout-section{margin:var(--mrd-space-4) 0}.mrd-layout-section__group-title.sc-mrd-layout-section{font-size:var(--mrd-font-size-xs);font-weight:var(--mrd-font-weight-semibold);color:var(--mrd-color-neutral-500);margin:0 0 var(--mrd-space-2) 0;padding-bottom:0;letter-spacing:0.01em}.mrd-layout-section__related-view.sc-mrd-layout-section{margin:var(--mrd-space-4) 0}.mrd-layout-section__related-view-title.sc-mrd-layout-section{font-size:var(--mrd-font-size-lg);font-weight:var(--mrd-font-weight-semibold);color:var(--mrd-color-neutral-800);margin:0 0 var(--mrd-space-3) 0}.mrd-layout-section__search.sc-mrd-layout-section{position:relative;margin:var(--mrd-space-2) 0}.mrd-layout-section__search-wrap.sc-mrd-layout-section{position:relative}.mrd-layout-section__search-icon.sc-mrd-layout-section{position:absolute;left:var(--mrd-input-padding-x);top:50%;transform:translateY(-50%);width:1rem;height:1rem;color:var(--mrd-color-neutral-400);pointer-events:none}.mrd-layout-section__search-input.sc-mrd-layout-section{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x) var(--mrd-input-padding-y) calc(var(--mrd-input-padding-x) + 1rem + var(--mrd-space-2));font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);outline:none;appearance:none;box-sizing:border-box}.mrd-layout-section__search-input.sc-mrd-layout-section:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-layout-section__search-input.sc-mrd-layout-section::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-layout-section__search-results.sc-mrd-layout-section{position:absolute;top:100%;left:0;right:0;background-color:var(--mrd-color-white);border:1px solid var(--mrd-color-neutral-300);border-top:none;border-radius:0 0 var(--mrd-border-radius) var(--mrd-border-radius);box-shadow:var(--mrd-shadow-sm);z-index:100;max-height:300px;overflow-y:auto;list-style:none;margin:0;padding:var(--mrd-space-1) 0}.mrd-layout-section__search-result.sc-mrd-layout-section{margin:0;padding:0}.mrd-layout-section__search-result-btn.sc-mrd-layout-section{display:flex;flex-direction:column;width:100%;padding:var(--mrd-space-2) var(--mrd-space-3);background:none;border:none;text-align:left;cursor:pointer;font-family:var(--mrd-font-family)}.mrd-layout-section__search-result-btn.sc-mrd-layout-section:hover{background-color:var(--mrd-color-primary-light)}.mrd-layout-section__search-result-label.sc-mrd-layout-section{font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-medium);color:var(--mrd-color-neutral-800)}.mrd-layout-section__search-result-desc.sc-mrd-layout-section{font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-500);margin-top:var(--mrd-space-1)}.mrd-layout-section__image-thumb-btn.sc-mrd-layout-section{background:none;border:none;padding:0;cursor:pointer;display:inline-block;border-radius:var(--mrd-border-radius);overflow:hidden;line-height:0}.mrd-layout-section__image-thumb-btn.sc-mrd-layout-section:hover .mrd-layout-section__image-thumb.sc-mrd-layout-section{opacity:0.85}.mrd-layout-section__image-thumb.sc-mrd-layout-section{display:block;max-width:160px;max-height:100px;border-radius:var(--mrd-border-radius);object-fit:cover;transition:opacity 0.15s}.mrd-layout-section__modal-backdrop.sc-mrd-layout-section{position:fixed;inset:0;background:rgba(0, 0, 0, 0.6);z-index:300;display:flex;align-items:center;justify-content:center}.mrd-layout-section__modal.sc-mrd-layout-section{position:relative;background:#fff;border-radius:var(--mrd-border-radius);padding:var(--mrd-space-3);max-width:min(90vw, 900px);max-height:90vh;display:flex;align-items:center;justify-content:center;box-shadow:var(--mrd-shadow-lg)}.mrd-layout-section__modal-close.sc-mrd-layout-section{position:absolute;top:var(--mrd-space-2);right:var(--mrd-space-2);background:rgba(0, 0, 0, 0.5);border:none;border-radius:50%;width:28px;height:28px;display:flex;align-items:center;justify-content:center;color:#fff;cursor:pointer;font-size:var(--mrd-font-size-sm);line-height:1;z-index:1}.mrd-layout-section__modal-close.sc-mrd-layout-section:hover{background:rgba(0, 0, 0, 0.8)}.mrd-layout-section__modal-image.sc-mrd-layout-section{display:block;max-width:100%;max-height:calc(90vh - 2rem);border-radius:var(--mrd-border-radius);object-fit:contain}`;
2936
+ /** FILE and IMAGE cells share the same download button. */
2937
+ function downloadLink(ctx, href, fileName, label) {
2938
+ return (index.h("button", { class: "mrd-layout-section__download-link", onClick: () => href && ctx.on.download({ href, fileName }) }, index.h("svg", { class: "mrd-layout-section__file-icon", viewBox: "0 0 24 24", "aria-hidden": "true" }, index.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" })), label));
2939
+ }
2940
+ function renderSingleFieldValue(ctx, item, value) {
2941
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
2942
+ const dt = item.dataType;
2943
+ switch (dt) {
2944
+ case index$1.ClientLayoutItemFieldDataType.HYPERLINK: {
2945
+ const v = value;
2946
+ const href = (_a = v === null || v === void 0 ? void 0 : v.href) !== null && _a !== void 0 ? _a : String(value);
2947
+ const label = (_d = (_c = (_b = v === null || v === void 0 ? void 0 : v.name) !== null && _b !== void 0 ? _b : v === null || v === void 0 ? void 0 : v.text) !== null && _c !== void 0 ? _c : v === null || v === void 0 ? void 0 : v.label) !== null && _d !== void 0 ? _d : href;
2948
+ return (index.h("a", { class: "mrd-layout-section__link", href: href, target: "_blank", rel: "noopener noreferrer" }, label));
2949
+ }
2950
+ case index$1.ClientLayoutItemFieldDataType.TEXTBLOCK:
2951
+ return index.h("div", { class: "mrd-layout-section__prose", innerHTML: String(value) });
2952
+ case index$1.ClientLayoutItemFieldDataType.LONGTEXT:
2953
+ return index.h("pre", { class: "mrd-layout-section__pre" }, String(value));
2954
+ case index$1.ClientLayoutItemFieldDataType.JSON:
2955
+ return index.h("pre", { class: "mrd-layout-section__pre", innerHTML: CellRenderer.formatJson(value) });
2956
+ case index$1.ClientLayoutItemFieldDataType.FILE: {
2957
+ const v = value;
2958
+ const fileName = (_e = v === null || v === void 0 ? void 0 : v.fileName) !== null && _e !== void 0 ? _e : String(value);
2959
+ const href = (_f = v === null || v === void 0 ? void 0 : v.href) !== null && _f !== void 0 ? _f : '';
2960
+ return downloadLink(ctx, href, fileName, t('download', ctx.locale));
2961
+ }
2962
+ case index$1.ClientLayoutItemFieldDataType.IMAGE: {
2963
+ const v = value;
2964
+ const href = (_g = v === null || v === void 0 ? void 0 : v.href) !== null && _g !== void 0 ? _g : '';
2965
+ const fileName = (_h = v === null || v === void 0 ? void 0 : v.fileName) !== null && _h !== void 0 ? _h : '';
2966
+ const previewUrl = ctx.imagePreviews[item.name];
2967
+ if (previewUrl) {
2968
+ return (index.h("button", { class: "mrd-layout-section__image-thumb-btn", onClick: () => ctx.on.openImage(previewUrl), title: fileName || undefined }, index.h("img", { class: "mrd-layout-section__image-thumb", src: previewUrl, alt: fileName })));
2969
+ }
2970
+ return downloadLink(ctx, href, fileName, fileName || href);
2971
+ }
2972
+ case index$1.ClientLayoutItemFieldDataType.BOOLEAN:
2973
+ return (index.h("span", { class: `mrd-layout-section__boolean mrd-layout-section__boolean--${value ? 'true' : 'false'}` }, value ? t('yes', ctx.locale) : t('no', ctx.locale)));
2974
+ case index$1.ClientLayoutItemFieldDataType.LIST: {
2975
+ const listItem = ((_j = item.listItems) !== null && _j !== void 0 ? _j : []).find(li => li.key === String(value));
2976
+ const label = (_k = listItem === null || listItem === void 0 ? void 0 : listItem.label) !== null && _k !== void 0 ? _k : String(value);
2977
+ const color = listItem === null || listItem === void 0 ? void 0 : listItem.color;
2978
+ const bg = listItem === null || listItem === void 0 ? void 0 : listItem.backgroundColor;
2979
+ if (color && bg) {
2980
+ return (index.h("span", { class: "mrd-layout-section__badge", style: { color, backgroundColor: bg } }, label));
2981
+ }
2982
+ if (color) {
2983
+ return (index.h("span", { class: "mrd-layout-section__badge-dot-row" }, index.h("span", { class: "mrd-layout-section__badge-dot", style: { backgroundColor: color } }), label));
2984
+ }
2985
+ return label;
2986
+ }
2987
+ case index$1.ClientLayoutItemFieldDataType.SECRET:
2988
+ return value ? index.h("span", { class: "mrd-layout-section__secret-masked" }, '••••••••') : null;
2989
+ default: {
2990
+ const text = CellRenderer.renderValue(dt, value, (_l = item.listItems) !== null && _l !== void 0 ? _l : [], ctx.locale);
2991
+ return text || null;
2992
+ }
2993
+ }
2994
+ }
2995
+ function renderFieldValue(ctx, item, rawValue) {
2996
+ if (rawValue == null || rawValue === '')
2997
+ return null;
2998
+ if (item.multiple && Array.isArray(rawValue)) {
2999
+ const rendered = rawValue.map(v => renderSingleFieldValue(ctx, item, v));
3000
+ if (rendered.every(r => typeof r === 'string' || r == null)) {
3001
+ return rendered.filter(Boolean).join(', ') || null;
3002
+ }
3003
+ return (index.h("span", null, rendered.map((r, i) => (index.h("span", { key: String(i) }, r, i < rendered.length - 1 ? ', ' : '')))));
3004
+ }
3005
+ return renderSingleFieldValue(ctx, item, rawValue);
3006
+ }
3007
+ function renderHistoryBadge(ctx, item, raw) {
3008
+ var _a, _b, _c;
3009
+ const hist = (_a = item.historyEnabled) !== null && _a !== void 0 ? _a : (_b = item.field) === null || _b === void 0 ? void 0 : _b.historyEnabled;
3010
+ if (!hist || !item.name)
3011
+ return null;
3012
+ const history = (_c = raw === null || raw === void 0 ? void 0 : raw.history) !== null && _c !== void 0 ? _c : [];
3013
+ if (!history.length)
3014
+ return null;
3015
+ const sorted = [...history].sort((a, b) => b.until.localeCompare(a.until));
3016
+ const isOpen = ctx.openHistoryField === item.name;
3017
+ return (index.h("span", { class: "mrd-layout-section__history-wrap" }, index.h("button", { type: "button", class: "mrd-layout-section__history-btn", title: t('history_badge_tooltip', ctx.locale), "aria-label": t('history_badge_tooltip', ctx.locale), onClick: (e) => {
3018
+ e.stopPropagation();
3019
+ ctx.on.toggleHistory(isOpen ? null : item.name);
3020
+ } }, index.h("svg", { class: "mrd-layout-section__history-icon", viewBox: "0 0 20 20", fill: "currentColor", "aria-hidden": "true" }, index.h("path", { "fill-rule": "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zm.75-13a.75.75 0 00-1.5 0v5c0 .207.085.394.22.53l2.5 2.5a.75.75 0 101.06-1.06L10.75 9.69V5z", "clip-rule": "evenodd" }))), isOpen && (index.h("div", { class: "mrd-layout-section__history-popover", role: "listbox" }, sorted.map((entry, i) => (index.h("div", { key: String(i), class: "mrd-layout-section__history-entry" }, entry.value, " (", t('history_until', ctx.locale), " ", formatDate(entry.until, ctx.locale), ")")))))));
3021
+ }
3022
+ function renderField(ctx, item) {
3023
+ var _a, _b;
3024
+ if (!item.name)
3025
+ return null;
3026
+ const raw = ctx.data[item.name];
3027
+ const hist = (_a = item.historyEnabled) !== null && _a !== void 0 ? _a : (_b = item.field) === null || _b === void 0 ? void 0 : _b.historyEnabled;
3028
+ const rawValue = hist && raw !== null && typeof raw === 'object' && 'current' in raw
3029
+ ? raw.current
3030
+ : raw;
3031
+ const renderedValue = renderFieldValue(ctx, item, rawValue);
3032
+ if (item.header) {
3033
+ return (index.h("h1", { class: "mrd-layout-section__field-header", key: item.name }, typeof renderedValue === 'string' ? renderedValue : rawValue != null ? String(rawValue) : item.label));
3034
+ }
3035
+ if (renderedValue == null)
3036
+ return null;
3037
+ const isBlock = item.dataType === index$1.ClientLayoutItemFieldDataType.TEXTBLOCK
3038
+ || item.dataType === index$1.ClientLayoutItemFieldDataType.LONGTEXT
3039
+ || item.dataType === index$1.ClientLayoutItemFieldDataType.JSON;
3040
+ return (index.h("div", { class: `mrd-layout-section__field${isBlock ? ' mrd-layout-section__field--block' : ''}`, key: item.name }, index.h("span", { class: "mrd-layout-section__field-label" }, item.label), index.h("span", { class: "mrd-layout-section__field-value" }, renderedValue, renderHistoryBadge(ctx, item, raw))));
3041
+ }
3042
+
3043
+ const mrdLayoutSectionCss = () => `.mrd-layout-section.sc-mrd-layout-section{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-color-neutral-800)}.mrd-layout-section__field.sc-mrd-layout-section{display:grid;grid-template-columns:200px 1fr;align-items:baseline;gap:0 var(--mrd-space-2);padding:var(--mrd-space-1) 0}.mrd-layout-section__field-label.sc-mrd-layout-section{font-size:var(--mrd-font-size-xs);font-weight:var(--mrd-font-weight-normal);color:var(--mrd-color-neutral-500);padding-top:1px}.mrd-layout-section__field-value.sc-mrd-layout-section{font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-medium);color:var(--mrd-color-neutral-800);word-break:break-word;display:inline-flex;align-items:center;gap:var(--mrd-space-1)}.mrd-layout-section__history-wrap.sc-mrd-layout-section{position:relative;display:inline-flex;align-items:center}.mrd-layout-section__history-btn.sc-mrd-layout-section{display:inline-flex;align-items:center;justify-content:center;width:1.25rem;height:1.25rem;padding:0;background:transparent;border:none;border-radius:var(--mrd-border-radius-sm);color:var(--mrd-color-neutral-400);cursor:pointer;flex-shrink:0;transition:color var(--mrd-transition-fast), background-color var(--mrd-transition-fast)}.mrd-layout-section__history-btn.sc-mrd-layout-section:hover{color:var(--mrd-color-neutral-700);background-color:var(--mrd-color-neutral-100)}.mrd-layout-section__history-btn.sc-mrd-layout-section:focus{outline:none;box-shadow:var(--mrd-shadow-focus)}.mrd-layout-section__history-icon.sc-mrd-layout-section{width:0.875rem;height:0.875rem}.mrd-layout-section__history-popover.sc-mrd-layout-section{position:absolute;top:calc(100% + 0.25rem);left:0;min-width:24rem;max-width:24rem;background-color:var(--mrd-color-white);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius-md);box-shadow:var(--mrd-shadow-md);padding:var(--mrd-space-1) 0;z-index:var(--mrd-z-dropdown)}.mrd-layout-section__history-entry.sc-mrd-layout-section{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-normal);color:var(--mrd-color-neutral-700);padding:var(--mrd-space-2) var(--mrd-space-3);line-height:var(--mrd-line-height-normal)}.mrd-layout-section__history-entry.sc-mrd-layout-section:not(:last-child){border-bottom:var(--mrd-border-width) solid var(--mrd-color-neutral-100)}.mrd-layout-section__field-header.sc-mrd-layout-section{font-size:var(--mrd-font-size-2xl);font-weight:var(--mrd-font-weight-bold);color:var(--mrd-color-neutral-900);margin:0 0 var(--mrd-space-4) 0;padding:0}.mrd-layout-section__header.sc-mrd-layout-section{font-size:var(--mrd-font-size-xl);font-weight:var(--mrd-font-weight-semibold);color:var(--mrd-color-neutral-800);margin:var(--mrd-space-4) 0 var(--mrd-space-2) 0;padding:0}.mrd-layout-section__text.sc-mrd-layout-section{font-size:var(--mrd-font-size-base);color:var(--mrd-color-neutral-700);line-height:var(--mrd-line-height-relaxed);margin:var(--mrd-space-2) 0}.mrd-layout-section__navigate.sc-mrd-layout-section{display:inline-flex;align-items:center;gap:var(--mrd-space-2);padding:var(--mrd-space-2) var(--mrd-space-3);background:none;border:1px solid var(--mrd-color-neutral-300);border-radius:var(--mrd-border-radius);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-primary);cursor:pointer;margin:var(--mrd-space-2) 0}.mrd-layout-section__navigate.sc-mrd-layout-section:hover{background-color:var(--mrd-color-primary-light);border-color:var(--mrd-color-primary)}.mrd-layout-section__link.sc-mrd-layout-section{color:var(--mrd-color-primary);text-decoration:none}.mrd-layout-section__link.sc-mrd-layout-section:hover{text-decoration:underline}.mrd-layout-section__relation-link.sc-mrd-layout-section{background:none;border:none;padding:0;font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-semibold);color:var(--mrd-color-primary);cursor:pointer;text-align:left}.mrd-layout-section__relation-link.sc-mrd-layout-section:hover{text-decoration:underline}.mrd-layout-section__download-link.sc-mrd-layout-section{display:inline-flex;align-items:center;gap:var(--mrd-space-1);background:none;border:none;padding:0;font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-primary);cursor:pointer;text-align:left}.mrd-layout-section__download-link.sc-mrd-layout-section:hover{text-decoration:underline;color:var(--mrd-color-primary-dark)}.mrd-layout-section__file-icon.sc-mrd-layout-section{flex-shrink:0;width:1rem;height:1rem}.mrd-layout-section__boolean--true.sc-mrd-layout-section{color:var(--mrd-color-success);font-weight:var(--mrd-font-weight-semibold)}.mrd-layout-section__boolean--false.sc-mrd-layout-section{color:var(--mrd-color-neutral-400)}.mrd-layout-section__field--block.sc-mrd-layout-section{grid-template-columns:1fr}.mrd-layout-section__badge.sc-mrd-layout-section{display:inline-block;font-size:var(--mrd-font-size-xs);font-weight:var(--mrd-font-weight-medium);padding:2px var(--mrd-space-3);border-radius:10px}.mrd-layout-section__badge-dot-row.sc-mrd-layout-section{display:inline-flex;align-items:center;gap:var(--mrd-space-2)}.mrd-layout-section__badge-dot.sc-mrd-layout-section{display:inline-block;width:10px;height:10px;border-radius:50%;flex-shrink:0}.mrd-layout-section__secret-masked.sc-mrd-layout-section{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-label-color);letter-spacing:0.15em;user-select:none;pointer-events:none}.mrd-layout-section__pre.sc-mrd-layout-section{font-family:var(--mrd-font-family-mono);font-size:var(--mrd-font-size-xs);background-color:var(--mrd-color-neutral-50);border:1px solid var(--mrd-color-neutral-200);border-radius:var(--mrd-border-radius);padding:var(--mrd-space-3);margin:0;max-height:calc(15 * var(--mrd-font-size-xs));overflow-x:auto;overflow-y:auto;white-space:pre-wrap;word-break:break-word}.mrd-layout-section__group.sc-mrd-layout-section{margin:var(--mrd-space-4) 0}.mrd-layout-section__group-title.sc-mrd-layout-section{font-size:var(--mrd-font-size-xs);font-weight:var(--mrd-font-weight-semibold);color:var(--mrd-color-neutral-500);margin:0 0 var(--mrd-space-2) 0;padding-bottom:0;letter-spacing:0.01em}.mrd-layout-section__related-view.sc-mrd-layout-section{margin:var(--mrd-space-4) 0}.mrd-layout-section__related-view-title.sc-mrd-layout-section{font-size:var(--mrd-font-size-lg);font-weight:var(--mrd-font-weight-semibold);color:var(--mrd-color-neutral-800);margin:0 0 var(--mrd-space-3) 0}.mrd-layout-section__search.sc-mrd-layout-section{position:relative;margin:var(--mrd-space-2) 0}.mrd-layout-section__search-wrap.sc-mrd-layout-section{position:relative}.mrd-layout-section__search-icon.sc-mrd-layout-section{position:absolute;left:var(--mrd-input-padding-x);top:50%;transform:translateY(-50%);width:1rem;height:1rem;color:var(--mrd-color-neutral-400);pointer-events:none}.mrd-layout-section__search-input.sc-mrd-layout-section{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x) var(--mrd-input-padding-y) calc(var(--mrd-input-padding-x) + 1rem + var(--mrd-space-2));font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);outline:none;appearance:none;box-sizing:border-box}.mrd-layout-section__search-input.sc-mrd-layout-section:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-layout-section__search-input.sc-mrd-layout-section::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-layout-section__search-results.sc-mrd-layout-section{position:absolute;top:100%;left:0;right:0;background-color:var(--mrd-color-white);border:1px solid var(--mrd-color-neutral-300);border-top:none;border-radius:0 0 var(--mrd-border-radius) var(--mrd-border-radius);box-shadow:var(--mrd-shadow-sm);z-index:100;max-height:300px;overflow-y:auto;list-style:none;margin:0;padding:var(--mrd-space-1) 0}.mrd-layout-section__search-result.sc-mrd-layout-section{margin:0;padding:0}.mrd-layout-section__search-result-btn.sc-mrd-layout-section{display:flex;flex-direction:column;width:100%;padding:var(--mrd-space-2) var(--mrd-space-3);background:none;border:none;text-align:left;cursor:pointer;font-family:var(--mrd-font-family)}.mrd-layout-section__search-result-btn.sc-mrd-layout-section:hover{background-color:var(--mrd-color-primary-light)}.mrd-layout-section__search-result-label.sc-mrd-layout-section{font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-medium);color:var(--mrd-color-neutral-800)}.mrd-layout-section__search-result-desc.sc-mrd-layout-section{font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-500);margin-top:var(--mrd-space-1)}.mrd-layout-section__image-thumb-btn.sc-mrd-layout-section{background:none;border:none;padding:0;cursor:pointer;display:inline-block;border-radius:var(--mrd-border-radius);overflow:hidden;line-height:0}.mrd-layout-section__image-thumb-btn.sc-mrd-layout-section:hover .mrd-layout-section__image-thumb.sc-mrd-layout-section{opacity:0.85}.mrd-layout-section__image-thumb.sc-mrd-layout-section{display:block;max-width:160px;max-height:100px;border-radius:var(--mrd-border-radius);object-fit:cover;transition:opacity 0.15s}.mrd-layout-section__modal-backdrop.sc-mrd-layout-section{position:fixed;inset:0;background:rgba(0, 0, 0, 0.6);z-index:300;display:flex;align-items:center;justify-content:center}.mrd-layout-section__modal.sc-mrd-layout-section{position:relative;background:var(--mrd-color-white);border-radius:var(--mrd-border-radius);padding:var(--mrd-space-3);max-width:min(90vw, 900px);max-height:90vh;display:flex;align-items:center;justify-content:center;box-shadow:var(--mrd-shadow-lg)}.mrd-layout-section__modal-close.sc-mrd-layout-section{position:absolute;top:var(--mrd-space-2);right:var(--mrd-space-2);background:rgba(0, 0, 0, 0.5);border:none;border-radius:50%;width:28px;height:28px;display:flex;align-items:center;justify-content:center;color:var(--mrd-color-white);cursor:pointer;font-size:var(--mrd-font-size-sm);line-height:1;z-index:1}.mrd-layout-section__modal-close.sc-mrd-layout-section:hover{background:rgba(0, 0, 0, 0.8)}.mrd-layout-section__modal-image.sc-mrd-layout-section{display:block;max-width:100%;max-height:calc(90vh - 2rem);border-radius:var(--mrd-border-radius);object-fit:contain}`;
2771
3044
 
2772
3045
  const MrdLayoutSection = class {
2773
3046
  constructor(hostRef) {
@@ -2849,14 +3122,8 @@ const MrdLayoutSection = class {
2849
3122
  }
2850
3123
  }
2851
3124
  }
2852
- viewKeyFor(item) {
2853
- var _a, _b, _c, _d;
2854
- if (item.type === index$1.ClientLayoutItemType.RELATED_VIEW)
2855
- return (_b = (_a = item.relatedClass) !== null && _a !== void 0 ? _a : item.name) !== null && _b !== void 0 ? _b : '';
2856
- return (_d = (_c = item.dataClass) !== null && _c !== void 0 ? _c : item.name) !== null && _d !== void 0 ? _d : '';
2857
- }
2858
3125
  emitLoadImages() {
2859
- for (const item of this.flattenItems(this.items)) {
3126
+ for (const item of flattenItems(this.items)) {
2860
3127
  if (item.type === index$1.ClientLayoutItemType.FIELD && item.dataType === index$1.ClientLayoutItemFieldDataType.IMAGE) {
2861
3128
  const fieldName = item.name;
2862
3129
  const raw = this.data[fieldName];
@@ -2866,15 +3133,6 @@ const MrdLayoutSection = class {
2866
3133
  }
2867
3134
  }
2868
3135
  }
2869
- flattenItems(items) {
2870
- const result = [];
2871
- for (const item of items) {
2872
- result.push(item);
2873
- if (item.items)
2874
- result.push(...this.flattenItems(item.items));
2875
- }
2876
- return result;
2877
- }
2878
3136
  /** Inject search results. Pass dataClass to target a specific SEARCH item; omit when there is only one. */
2879
3137
  async setSearchResults(results, dataClass) {
2880
3138
  const key = dataClass !== null && dataClass !== void 0 ? dataClass : this.resolveSearchKey();
@@ -2940,113 +3198,26 @@ const MrdLayoutSection = class {
2940
3198
  }
2941
3199
  resolveSearchKey() {
2942
3200
  var _a;
2943
- const items = this.flattenItems(this.items).filter(i => i.type === index$1.ClientLayoutItemType.SEARCH);
3201
+ const items = flattenItems(this.items).filter(i => i.type === index$1.ClientLayoutItemType.SEARCH);
2944
3202
  if (items.length === 1)
2945
3203
  return (_a = items[0].dataClass) !== null && _a !== void 0 ? _a : null;
2946
- return null;
2947
- }
2948
- renderSingleFieldValue(item, value) {
2949
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
2950
- const dt = item.dataType;
2951
- switch (dt) {
2952
- case index$1.ClientLayoutItemFieldDataType.HYPERLINK: {
2953
- const v = value;
2954
- const href = (_a = v === null || v === void 0 ? void 0 : v.href) !== null && _a !== void 0 ? _a : String(value);
2955
- const label = (_d = (_c = (_b = v === null || v === void 0 ? void 0 : v.name) !== null && _b !== void 0 ? _b : v === null || v === void 0 ? void 0 : v.text) !== null && _c !== void 0 ? _c : v === null || v === void 0 ? void 0 : v.label) !== null && _d !== void 0 ? _d : href;
2956
- return (index.h("a", { class: "mrd-layout-section__link", href: href, target: "_blank", rel: "noopener noreferrer" }, label));
2957
- }
2958
- case index$1.ClientLayoutItemFieldDataType.TEXTBLOCK:
2959
- return index.h("div", { class: "mrd-layout-section__prose", innerHTML: String(value) });
2960
- case index$1.ClientLayoutItemFieldDataType.LONGTEXT:
2961
- return index.h("pre", { class: "mrd-layout-section__pre" }, String(value));
2962
- case index$1.ClientLayoutItemFieldDataType.JSON:
2963
- return index.h("pre", { class: "mrd-layout-section__pre", innerHTML: CellRenderer.formatJson(value) });
2964
- case index$1.ClientLayoutItemFieldDataType.FILE: {
2965
- const v = value;
2966
- const fileName = (_e = v === null || v === void 0 ? void 0 : v.fileName) !== null && _e !== void 0 ? _e : String(value);
2967
- const href = (_f = v === null || v === void 0 ? void 0 : v.href) !== null && _f !== void 0 ? _f : '';
2968
- return (index.h("button", { class: "mrd-layout-section__download-link", onClick: () => href && this.mrdDownload.emit({ href, fileName }) }, index.h("svg", { class: "mrd-layout-section__file-icon", viewBox: "0 0 24 24", "aria-hidden": "true" }, index.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)));
2969
- }
2970
- case index$1.ClientLayoutItemFieldDataType.IMAGE: {
2971
- const v = value;
2972
- const href = (_g = v === null || v === void 0 ? void 0 : v.href) !== null && _g !== void 0 ? _g : '';
2973
- const fileName = (_h = v === null || v === void 0 ? void 0 : v.fileName) !== null && _h !== void 0 ? _h : '';
2974
- const previewUrl = this.imagePreviews[item.name];
2975
- if (previewUrl) {
2976
- return (index.h("button", { class: "mrd-layout-section__image-thumb-btn", onClick: () => { this.imagePreviewUrl = previewUrl; }, title: fileName || undefined }, index.h("img", { class: "mrd-layout-section__image-thumb", src: previewUrl, alt: fileName })));
2977
- }
2978
- return (index.h("button", { class: "mrd-layout-section__download-link", onClick: () => href && this.mrdDownload.emit({ href, fileName }) }, index.h("svg", { class: "mrd-layout-section__file-icon", viewBox: "0 0 24 24", "aria-hidden": "true" }, index.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" })), fileName || href));
2979
- }
2980
- case index$1.ClientLayoutItemFieldDataType.BOOLEAN:
2981
- return (index.h("span", { class: `mrd-layout-section__boolean mrd-layout-section__boolean--${value ? 'true' : 'false'}` }, value ? t('yes', this.locale) : t('no', this.locale)));
2982
- case index$1.ClientLayoutItemFieldDataType.LIST: {
2983
- const listItem = ((_j = item.listItems) !== null && _j !== void 0 ? _j : []).find(li => li.key === String(value));
2984
- const label = (_k = listItem === null || listItem === void 0 ? void 0 : listItem.label) !== null && _k !== void 0 ? _k : String(value);
2985
- const color = listItem === null || listItem === void 0 ? void 0 : listItem.color;
2986
- const bg = listItem === null || listItem === void 0 ? void 0 : listItem.backgroundColor;
2987
- if (color && bg) {
2988
- return (index.h("span", { class: "mrd-layout-section__badge", style: { color, backgroundColor: bg } }, label));
2989
- }
2990
- if (color) {
2991
- return (index.h("span", { class: "mrd-layout-section__badge-dot-row" }, index.h("span", { class: "mrd-layout-section__badge-dot", style: { backgroundColor: color } }), label));
2992
- }
2993
- return label;
2994
- }
2995
- case index$1.ClientLayoutItemFieldDataType.SECRET:
2996
- return value ? index.h("span", { class: "mrd-layout-section__secret-masked" }, '••••••••') : null;
2997
- default: {
2998
- const text = CellRenderer.renderValue(dt, value, (_l = item.listItems) !== null && _l !== void 0 ? _l : [], this.locale);
2999
- return text || null;
3000
- }
3001
- }
3002
- }
3003
- renderFieldValue(item, rawValue) {
3004
- if (rawValue == null || rawValue === '')
3005
- return null;
3006
- if (item.multiple && Array.isArray(rawValue)) {
3007
- const rendered = rawValue.map(v => this.renderSingleFieldValue(item, v));
3008
- if (rendered.every(r => typeof r === 'string' || r == null)) {
3009
- return rendered.filter(Boolean).join(', ') || null;
3010
- }
3011
- return (index.h("span", null, rendered.map((r, i) => (index.h("span", { key: String(i) }, r, i < rendered.length - 1 ? ', ' : '')))));
3012
- }
3013
- return this.renderSingleFieldValue(item, rawValue);
3204
+ return null;
3014
3205
  }
3015
- renderHistoryBadge(item, raw) {
3016
- var _a, _b, _c;
3017
- const hist = (_a = item.historyEnabled) !== null && _a !== void 0 ? _a : (_b = item.field) === null || _b === void 0 ? void 0 : _b.historyEnabled;
3018
- if (!hist || !item.name)
3019
- return null;
3020
- const history = (_c = raw === null || raw === void 0 ? void 0 : raw.history) !== null && _c !== void 0 ? _c : [];
3021
- if (!history.length)
3022
- return null;
3023
- const sorted = [...history].sort((a, b) => b.until.localeCompare(a.until));
3024
- const isOpen = this.openHistoryField === item.name;
3025
- const { locale } = this;
3026
- return (index.h("span", { class: "mrd-layout-section__history-wrap" }, index.h("button", { type: "button", class: "mrd-layout-section__history-btn", title: t('history_badge_tooltip', locale), "aria-label": t('history_badge_tooltip', locale), onClick: (e) => {
3027
- e.stopPropagation();
3028
- this.openHistoryField = isOpen ? null : item.name;
3029
- } }, index.h("svg", { class: "mrd-layout-section__history-icon", viewBox: "0 0 20 20", fill: "currentColor", "aria-hidden": "true" }, index.h("path", { "fill-rule": "evenodd", d: "M10 18a8 8 0 100-16 8 8 0 000 16zm.75-13a.75.75 0 00-1.5 0v5c0 .207.085.394.22.53l2.5 2.5a.75.75 0 101.06-1.06L10.75 9.69V5z", "clip-rule": "evenodd" }))), isOpen && (index.h("div", { class: "mrd-layout-section__history-popover", role: "listbox" }, sorted.map((entry, i) => (index.h("div", { key: String(i), class: "mrd-layout-section__history-entry" }, entry.value, " (", t('history_until', locale), " ", formatDate(entry.until, locale), ")")))))));
3206
+ fieldCtx() {
3207
+ return {
3208
+ locale: this.locale,
3209
+ data: this.data,
3210
+ imagePreviews: this.imagePreviews,
3211
+ openHistoryField: this.openHistoryField,
3212
+ on: {
3213
+ download: detail => this.mrdDownload.emit(detail),
3214
+ openImage: url => { this.imagePreviewUrl = url; },
3215
+ toggleHistory: fieldName => { this.openHistoryField = fieldName; },
3216
+ },
3217
+ };
3030
3218
  }
3031
3219
  renderField(item) {
3032
- var _a, _b;
3033
- if (!item.name)
3034
- return null;
3035
- const raw = this.data[item.name];
3036
- const hist = (_a = item.historyEnabled) !== null && _a !== void 0 ? _a : (_b = item.field) === null || _b === void 0 ? void 0 : _b.historyEnabled;
3037
- const rawValue = hist && raw !== null && typeof raw === 'object' && 'current' in raw
3038
- ? raw.current
3039
- : raw;
3040
- const renderedValue = this.renderFieldValue(item, rawValue);
3041
- if (item.header) {
3042
- return (index.h("h1", { class: "mrd-layout-section__field-header", key: item.name }, typeof renderedValue === 'string' ? renderedValue : rawValue != null ? String(rawValue) : item.label));
3043
- }
3044
- if (renderedValue == null)
3045
- return null;
3046
- const isBlock = item.dataType === index$1.ClientLayoutItemFieldDataType.TEXTBLOCK
3047
- || item.dataType === index$1.ClientLayoutItemFieldDataType.LONGTEXT
3048
- || item.dataType === index$1.ClientLayoutItemFieldDataType.JSON;
3049
- return (index.h("div", { class: `mrd-layout-section__field${isBlock ? ' mrd-layout-section__field--block' : ''}`, key: item.name }, index.h("span", { class: "mrd-layout-section__field-label" }, item.label), index.h("span", { class: "mrd-layout-section__field-value" }, renderedValue, this.renderHistoryBadge(item, raw))));
3220
+ return renderField(this.fieldCtx(), item);
3050
3221
  }
3051
3222
  renderRelation(item) {
3052
3223
  var _a, _b, _c;
@@ -3079,7 +3250,7 @@ const MrdLayoutSection = class {
3079
3250
  }
3080
3251
  renderRelatedView(item) {
3081
3252
  var _a, _b, _c, _d, _e, _f, _g, _h;
3082
- const key = this.viewKeyFor(item);
3253
+ const key = viewKeyFor(item);
3083
3254
  if (!key)
3084
3255
  return null;
3085
3256
  if (!item.view)
@@ -3091,15 +3262,19 @@ const MrdLayoutSection = class {
3091
3262
  // The API publishes `archetypes` on the VIEW/RELATED_VIEW item itself
3092
3263
  // (sibling of `view`), not inside `view`.
3093
3264
  const docArchetype = index$1.resolveArchetype((_g = item.archetypes) !== null && _g !== void 0 ? _g : (_h = item.view) === null || _h === void 0 ? void 0 : _h.archetypes, index$1.ARCHETYPE_DOCUMENT);
3265
+ // Canonical parent href for single-container seeding: use the RELATED_VIEW's
3266
+ // fromClass (base class) rather than the route class, so polymorphic subtypes
3267
+ // resolve to the same container the documents actually reference.
3268
+ const containerHref = buildContainerHref(item, selfHref, parentId);
3094
3269
  return (index.h("div", { class: "mrd-layout-section__related-view", key: `view-${key}` }, showTitle && item.label && index.h("h3", { class: "mrd-layout-section__related-view-title" }, item.label), docArchetype
3095
- ? this.renderDocumentContainer(item, key, parentId, docArchetype)
3270
+ ? this.renderDocumentContainer(item, key, parentId, docArchetype, containerHref)
3096
3271
  : this.renderTable(item, key, parentId)));
3097
3272
  }
3098
3273
  /** Document collection view: owns the view-switch + collection actions and
3099
3274
  * swaps between the folder tree and the flat table. Events are re-emitted to
3100
3275
  * the host with the view key, exactly as the raw list/table events were. */
3101
- renderDocumentContainer(item, key, parentId, archetype) {
3102
- return (index.h("mrd-document-container", { item: item, archetype: archetype, parentId: parentId, viewKey: key, locale: this.locale, onMrdLoadDistinct: (e) => {
3276
+ renderDocumentContainer(item, key, parentId, archetype, containerHref) {
3277
+ return (index.h("mrd-document-container", { item: item, archetype: archetype, parentId: parentId, containerHref: containerHref, viewKey: key, locale: this.locale, onMrdLoadDistinct: (e) => {
3103
3278
  e.stopPropagation();
3104
3279
  this.mrdLoadViewDistinct.emit(Object.assign({ name: key }, e.detail));
3105
3280
  }, onMrdLoadPage: (e) => {
@@ -3195,7 +3370,7 @@ const MrdLayoutSection = class {
3195
3370
  }
3196
3371
  render() {
3197
3372
  const docArchetype = index$1.resolveArchetype(this.archetypes, index$1.ARCHETYPE_DOCUMENT);
3198
- return (index.h(index.Host, { key: '6e737354daec0137b6ebe304efcce9990f02739f' }, index.h("div", { key: '31a73a8a78999793f5dacee5f2da41df5f23156e', class: "mrd-layout-section" }, docArchetype
3373
+ return (index.h(index.Host, { key: '5d778188356a25ea13d45745dc5ed573ab2b2ef0' }, index.h("div", { key: '0b673a4bcf8b36cd21662bb8a3506cc3f30edb04', class: "mrd-layout-section" }, docArchetype
3199
3374
  ? this.renderDocumentObject(docArchetype)
3200
3375
  : this.items.map(item => this.renderItem(item))), this.renderImageModal()));
3201
3376
  }
@@ -3206,9 +3381,9 @@ const MrdLayoutSection = class {
3206
3381
  }]
3207
3382
  }; }
3208
3383
  };
3209
- MrdLayoutSection.style = mrdLayoutSectionScss();
3384
+ MrdLayoutSection.style = mrdLayoutSectionCss();
3210
3385
 
3211
- const mrdListFieldScss = () => `.sc-mrd-list-field-h{display:block}.mrd-list-field.sc-mrd-list-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-list-field__label.sc-mrd-list-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-list-field__label--required.sc-mrd-list-field::after{content:' *';color:var(--mrd-color-danger)}.mrd-list-field__select.sc-mrd-list-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);padding-right:calc(var(--mrd-input-padding-x) + 1.5rem);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right var(--mrd-space-3) center;border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;cursor:pointer;box-sizing:border-box}.mrd-list-field__select.sc-mrd-list-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-list-field__select.sc-mrd-list-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-list-field__select--error.sc-mrd-list-field{border-color:var(--mrd-border-color-error)}.mrd-list-field__select--error.sc-mrd-list-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-list-field__checkbox-list.sc-mrd-list-field{display:flex;flex-direction:column;gap:var(--mrd-space-2);padding:var(--mrd-space-3);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);background-color:var(--mrd-input-bg)}.mrd-list-field__checkbox-list--error.sc-mrd-list-field{border-color:var(--mrd-border-color-error)}.mrd-list-field__checkbox-item.sc-mrd-list-field{display:flex;align-items:center;gap:var(--mrd-space-2);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);cursor:pointer}.mrd-list-field__checkbox-item.sc-mrd-list-field input[type='checkbox'].sc-mrd-list-field{width:1rem;height:1rem;cursor:pointer;accent-color:var(--mrd-color-primary)}.mrd-list-field__color-dot.sc-mrd-list-field{display:inline-block;width:12px;height:12px;border-radius:50%;flex-shrink:0}.mrd-list-field__error.sc-mrd-list-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}`;
3386
+ const mrdListFieldCss = () => `.sc-mrd-list-field-h{display:block}.mrd-list-field.sc-mrd-list-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-list-field__label.sc-mrd-list-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-list-field__label--required.sc-mrd-list-field::after{content:" *";color:var(--mrd-color-danger)}.mrd-list-field__select.sc-mrd-list-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box}.mrd-list-field__select.sc-mrd-list-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-list-field__select.sc-mrd-list-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-list-field__select.sc-mrd-list-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-list-field__select--error.sc-mrd-list-field{border-color:var(--mrd-border-color-error)}.mrd-list-field__select--error.sc-mrd-list-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-list-field__select.sc-mrd-list-field{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right var(--mrd-space-3) center;padding-right:calc(var(--mrd-input-padding-x) + 1.5rem);cursor:pointer}.mrd-list-field__error.sc-mrd-list-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}.mrd-list-field__checkbox-list.sc-mrd-list-field{display:flex;flex-direction:column;gap:var(--mrd-space-2);padding:var(--mrd-space-3);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);background-color:var(--mrd-input-bg)}.mrd-list-field__checkbox-list--error.sc-mrd-list-field{border-color:var(--mrd-border-color-error)}.mrd-list-field__checkbox-item.sc-mrd-list-field{display:flex;align-items:center;gap:var(--mrd-space-2);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);cursor:pointer}.mrd-list-field__checkbox-item.sc-mrd-list-field input[type=checkbox].sc-mrd-list-field{width:1rem;height:1rem;cursor:pointer;accent-color:var(--mrd-color-primary)}.mrd-list-field__color-dot.sc-mrd-list-field{display:inline-block;width:12px;height:12px;border-radius:50%;flex-shrink:0}`;
3212
3387
 
3213
3388
  const MrdListField = class {
3214
3389
  constructor(hostRef) {
@@ -3231,22 +3406,12 @@ const MrdListField = class {
3231
3406
  if (this.multiple) {
3232
3407
  const vals = Array.from(select.selectedOptions).map(o => o.value);
3233
3408
  this.selected = vals;
3234
- if (this.required && !validateRequired(vals)) {
3235
- this.error = t('required', this.locale);
3236
- }
3237
- else {
3238
- this.error = '';
3239
- }
3409
+ this.error = requiredError(vals, this.required, this.locale);
3240
3410
  this.mrdChange.emit({ name: this.name, value: vals });
3241
3411
  }
3242
3412
  else {
3243
3413
  const val = select.value;
3244
- if (this.required && !validateRequired(val)) {
3245
- this.error = t('required', this.locale);
3246
- }
3247
- else {
3248
- this.error = '';
3249
- }
3414
+ this.error = requiredError(val, this.required, this.locale);
3250
3415
  this.mrdChange.emit({ name: this.name, value: val });
3251
3416
  }
3252
3417
  };
@@ -3261,12 +3426,7 @@ const MrdListField = class {
3261
3426
  else {
3262
3427
  this.selected = [...this.selected, key];
3263
3428
  }
3264
- if (this.required && !validateRequired(this.selected)) {
3265
- this.error = t('required', this.locale);
3266
- }
3267
- else {
3268
- this.error = '';
3269
- }
3429
+ this.error = requiredError(this.selected, this.required, this.locale);
3270
3430
  this.mrdChange.emit({ name: this.name, value: this.selected });
3271
3431
  };
3272
3432
  }
@@ -3290,22 +3450,22 @@ const MrdListField = class {
3290
3450
  const hasError = !!this.error;
3291
3451
  const currentValue = Array.isArray(this.value) ? ((_a = this.value[0]) !== null && _a !== void 0 ? _a : '') : ((_b = this.value) !== null && _b !== void 0 ? _b : '');
3292
3452
  if (this.multiple) {
3293
- return (index.h(index.Host, null, index.h("div", { class: "mrd-list-field" }, this.label && (index.h("label", { class: `mrd-list-field__label${this.required ? ' mrd-list-field__label--required' : ''}` }, this.label)), index.h("div", { class: `mrd-list-field__checkbox-list${hasError ? ' mrd-list-field__checkbox-list--error' : ''}` }, this.listItems.map(lv => {
3453
+ return (index.h(index.Host, null, index.h("div", { class: "mrd-list-field" }, index.h(FieldLabel, { base: "mrd-list-field", label: this.label, required: this.required }), index.h("div", { class: controlClass('mrd-list-field', hasError, 'checkbox-list') }, this.listItems.map(lv => {
3294
3454
  var _a, _b;
3295
3455
  return (index.h("label", { key: lv.key, class: "mrd-list-field__checkbox-item" }, index.h("input", { type: "checkbox", checked: this.selected.includes(lv.key), disabled: this.disabled, onChange: () => this.toggleCheckbox(lv.key) }), (lv.color || lv.backgroundColor) && (index.h("span", { class: "mrd-list-field__color-dot", style: { backgroundColor: (_b = (_a = lv.backgroundColor) !== null && _a !== void 0 ? _a : lv.color) !== null && _b !== void 0 ? _b : '' } })), index.h("span", null, lv.label)));
3296
- })), hasError && index.h("span", { class: "mrd-list-field__error" }, this.error))));
3456
+ })), index.h(FieldError, { base: "mrd-list-field", error: this.error }))));
3297
3457
  }
3298
- return (index.h(index.Host, null, index.h("div", { class: "mrd-list-field" }, this.label && (index.h("label", { class: `mrd-list-field__label${this.required ? ' mrd-list-field__label--required' : ''}` }, this.label)), index.h("select", { class: `mrd-list-field__select${hasError ? ' mrd-list-field__select--error' : ''}`, name: this.name, required: this.required, disabled: this.disabled, onChange: this.handleSelectChange, onBlur: this.handleBlur }, index.h("option", { value: "" }, t('select_placeholder', this.locale)), this.listItems.map(lv => {
3458
+ return (index.h(index.Host, null, index.h("div", { class: "mrd-list-field" }, index.h(FieldLabel, { base: "mrd-list-field", label: this.label, required: this.required }), index.h("select", { class: controlClass('mrd-list-field', hasError, 'select'), name: this.name, required: this.required, disabled: this.disabled, onChange: this.handleSelectChange, onBlur: this.handleBlur }, index.h("option", { value: "" }, t('select_placeholder', this.locale)), this.listItems.map(lv => {
3299
3459
  var _a, _b;
3300
3460
  const bg = (_b = (_a = lv.backgroundColor) !== null && _a !== void 0 ? _a : lv.color) !== null && _b !== void 0 ? _b : null;
3301
3461
  const style = bg ? { backgroundColor: bg, color: this.getContrastColor(bg) } : {};
3302
3462
  return (index.h("option", { key: lv.key, value: lv.key, selected: lv.key === currentValue, style: style }, lv.label));
3303
- })), hasError && index.h("span", { class: "mrd-list-field__error" }, this.error))));
3463
+ })), index.h(FieldError, { base: "mrd-list-field", error: this.error }))));
3304
3464
  }
3305
3465
  };
3306
- MrdListField.style = mrdListFieldScss();
3466
+ MrdListField.style = mrdListFieldCss();
3307
3467
 
3308
- const mrdLongtextFieldScss = () => `.sc-mrd-longtext-field-h{display:block}.mrd-longtext-field.sc-mrd-longtext-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-longtext-field__label.sc-mrd-longtext-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-longtext-field__label--required.sc-mrd-longtext-field::after{content:' *';color:var(--mrd-color-danger)}.mrd-longtext-field__input.sc-mrd-longtext-field{display:block;width:100%;min-height:calc(var(--mrd-input-height) * 5);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;resize:vertical;box-sizing:border-box;line-height:1.5}.mrd-longtext-field__input.sc-mrd-longtext-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-longtext-field__input.sc-mrd-longtext-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-longtext-field__input--error.sc-mrd-longtext-field{border-color:var(--mrd-border-color-error)}.mrd-longtext-field__input--error.sc-mrd-longtext-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-longtext-field__content.sc-mrd-longtext-field{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);white-space:pre-wrap;word-break:break-word;margin:0;padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);background-color:var(--mrd-input-bg-disabled);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);line-height:1.5}.mrd-longtext-field__error.sc-mrd-longtext-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}`;
3468
+ const mrdLongtextFieldCss = () => `.sc-mrd-longtext-field-h{display:block}.mrd-longtext-field.sc-mrd-longtext-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-longtext-field__label.sc-mrd-longtext-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-longtext-field__label--required.sc-mrd-longtext-field::after{content:" *";color:var(--mrd-color-danger)}.mrd-longtext-field__input.sc-mrd-longtext-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box}.mrd-longtext-field__input.sc-mrd-longtext-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-longtext-field__input.sc-mrd-longtext-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-longtext-field__input.sc-mrd-longtext-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-longtext-field__input--error.sc-mrd-longtext-field{border-color:var(--mrd-border-color-error)}.mrd-longtext-field__input--error.sc-mrd-longtext-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-longtext-field__error.sc-mrd-longtext-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}.mrd-longtext-field__input.sc-mrd-longtext-field{height:auto;min-height:calc(var(--mrd-input-height) * 5);resize:vertical;line-height:1.5}.mrd-longtext-field__content.sc-mrd-longtext-field{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);white-space:pre-wrap;word-break:break-word;margin:0;padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);background-color:var(--mrd-input-bg-disabled);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);line-height:1.5}`;
3309
3469
 
3310
3470
  const MrdLongtextField = class {
3311
3471
  constructor(hostRef) {
@@ -3326,23 +3486,17 @@ const MrdLongtextField = class {
3326
3486
  };
3327
3487
  this.handleBlur = (e) => {
3328
3488
  const val = e.target.value;
3329
- if (this.required && !validateRequired(val)) {
3330
- this.error = t('required', this.locale);
3331
- }
3332
- else {
3333
- this.error = '';
3334
- }
3489
+ this.error = requiredError(val, this.required, this.locale);
3335
3490
  this.mrdBlur.emit({ name: this.name, value: val });
3336
3491
  };
3337
3492
  }
3338
3493
  render() {
3339
- const hasError = !!this.error;
3340
- return (index.h(index.Host, { key: 'f00f81944748f8f09e22d44befe5e288456b7cc8' }, index.h("div", { key: '7b0ae9cf5b6b684cddb648fe4db6005494322535', class: "mrd-longtext-field" }, this.label && (index.h("label", { key: '3fc6a8710d0e98fe685c45d214a88ae1b0947973', class: `mrd-longtext-field__label${this.required ? ' mrd-longtext-field__label--required' : ''}` }, this.label)), this.disabled ? (index.h("pre", { class: "mrd-longtext-field__content" }, this.value)) : (index.h("textarea", { class: `mrd-longtext-field__input${hasError ? ' mrd-longtext-field__input--error' : ''}`, name: this.name, placeholder: this.placeholder, required: this.required, rows: 10, onInput: this.handleInput, onBlur: this.handleBlur }, this.value)), hasError && index.h("span", { key: 'e96f1dbc6c00a1602f4ce3c97d514a229aeb7cb7', class: "mrd-longtext-field__error" }, this.error))));
3494
+ return (index.h(index.Host, { key: '1d23db1324fa0fc97a07fdae65f2d84e43419a72' }, index.h("div", { key: '0ad2b262088aa3745f088a44af26649593805840', class: "mrd-longtext-field" }, index.h(FieldLabel, { key: '5a78739d6ced4e2df77589b64c66401819c4b5c7', base: "mrd-longtext-field", label: this.label, required: this.required }), this.disabled ? (index.h("pre", { class: "mrd-longtext-field__content" }, this.value)) : (index.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)), index.h(FieldError, { key: '5b870a75b518e2808518b83c9abebf8589a86108', base: "mrd-longtext-field", error: this.error }))));
3341
3495
  }
3342
3496
  };
3343
- MrdLongtextField.style = mrdLongtextFieldScss();
3497
+ MrdLongtextField.style = mrdLongtextFieldCss();
3344
3498
 
3345
- const mrdNumberFieldScss = () => `.sc-mrd-number-field-h{display:block}.mrd-number-field.sc-mrd-number-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-number-field__label.sc-mrd-number-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-number-field__label--required.sc-mrd-number-field::after{content:' *';color:var(--mrd-color-danger)}.mrd-number-field__input-wrapper.sc-mrd-number-field{position:relative;display:flex;align-items:center}.mrd-number-field__input.sc-mrd-number-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box;text-align:right}.mrd-number-field__input.sc-mrd-number-field::placeholder{color:var(--mrd-input-placeholder-color);text-align:left}.mrd-number-field__input.sc-mrd-number-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-number-field__input.sc-mrd-number-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-number-field__input--error.sc-mrd-number-field{border-color:var(--mrd-border-color-error)}.mrd-number-field__input--error.sc-mrd-number-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-number-field__error.sc-mrd-number-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}`;
3499
+ const mrdNumberFieldCss = () => `.sc-mrd-number-field-h{display:block}.mrd-number-field.sc-mrd-number-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-number-field__label.sc-mrd-number-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-number-field__label--required.sc-mrd-number-field::after{content:" *";color:var(--mrd-color-danger)}.mrd-number-field__input-wrapper.sc-mrd-number-field{position:relative;display:flex;align-items:center}.mrd-number-field__input.sc-mrd-number-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box}.mrd-number-field__input.sc-mrd-number-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-number-field__input.sc-mrd-number-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-number-field__input.sc-mrd-number-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-number-field__input--error.sc-mrd-number-field{border-color:var(--mrd-border-color-error)}.mrd-number-field__input--error.sc-mrd-number-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-number-field__input.sc-mrd-number-field{text-align:right}.mrd-number-field__input.sc-mrd-number-field::placeholder{text-align:left}.mrd-number-field__error.sc-mrd-number-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}`;
3346
3500
 
3347
3501
  const MrdNumberField = class {
3348
3502
  constructor(hostRef) {
@@ -3413,12 +3567,12 @@ const MrdNumberField = class {
3413
3567
  const hasError = !!this.error;
3414
3568
  const suffix = this.dataType === index$1.ClientLayoutItemFieldDataType.PERCENTAGE ? '%' :
3415
3569
  this.dataType === index$1.ClientLayoutItemFieldDataType.DECIMAL ? '' : '';
3416
- return (index.h(index.Host, { key: 'b034a3cc8d841641c0ec167e138904586b044121' }, index.h("div", { key: '7379bfadb8bd0c4e0a945a37013053a4e22477ab', class: "mrd-number-field" }, this.label && (index.h("label", { key: '5518d40b7158e17704633c2b95ac7e3efc0c5568', class: `mrd-number-field__label${this.required ? ' mrd-number-field__label--required' : ''}` }, this.label)), index.h("div", { key: '38ad9f3c945d66c23bd77c743306e916eaefed7f', class: "mrd-number-field__input-wrapper" }, index.h("input", { key: 'ac8b4bc1ea4431cc9306664522ebfda21760ae83', class: `mrd-number-field__input${hasError ? ' mrd-number-field__input--error' : ''}`, 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 })), hasError && index.h("span", { key: '09f5a58b769c81acdf4bdd48f9325934c4bb875d', class: "mrd-number-field__error" }, this.error))));
3570
+ return (index.h(index.Host, { key: 'fd7220e0a7f574ab0c61094a9ba7fd764e1adafd' }, index.h("div", { key: 'ef6118a339c9766f187cd2b1fa3fcc85ef8cb69f', class: "mrd-number-field" }, index.h(FieldLabel, { key: '015207ae65df07f7ee7bbc24ccab45524176dbf7', base: "mrd-number-field", label: this.label, required: this.required }), index.h("div", { key: '954b99cbcf4002b0336810e354f1a46d39cb8076', class: "mrd-number-field__input-wrapper" }, index.h("input", { key: 'dddc08e090b200736d186960db1436e44f42703c', 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 })), index.h(FieldError, { key: '87e12bd737aed0a845470cef66d7a6d61d11de0b', base: "mrd-number-field", error: this.error }))));
3417
3571
  }
3418
3572
  };
3419
- MrdNumberField.style = mrdNumberFieldScss();
3573
+ MrdNumberField.style = mrdNumberFieldCss();
3420
3574
 
3421
- const mrdRelationFieldScss = () => `.sc-mrd-relation-field-h{display:block}.mrd-relation-field.sc-mrd-relation-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%;position:relative}.mrd-relation-field__label.sc-mrd-relation-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-relation-field__label--required.sc-mrd-relation-field::after{content:' *';color:var(--mrd-color-danger)}.mrd-relation-field__select.sc-mrd-relation-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);padding-right:calc(var(--mrd-input-padding-x) + 1.5rem);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right var(--mrd-space-3) center;border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);outline:none;appearance:none;cursor:pointer;box-sizing:border-box}.mrd-relation-field__select.sc-mrd-relation-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-relation-field__select.sc-mrd-relation-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-relation-field__select--error.sc-mrd-relation-field{border-color:var(--mrd-border-color-error)}.mrd-relation-field__select--error.sc-mrd-relation-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-relation-field__tags.sc-mrd-relation-field{display:flex;flex-wrap:wrap;gap:var(--mrd-space-1);margin-bottom:var(--mrd-space-1)}.mrd-relation-field__tag.sc-mrd-relation-field{display:inline-flex;align-items:center;gap:var(--mrd-space-1);padding:var(--mrd-space-1) var(--mrd-space-2);background-color:var(--mrd-color-primary-light);color:var(--mrd-color-primary-dark);border-radius:var(--mrd-border-radius-full);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-medium)}.mrd-relation-field__tag-remove.sc-mrd-relation-field{background:none;border:none;cursor:pointer;color:var(--mrd-color-primary-dark);font-size:var(--mrd-font-size-xs);padding:0;line-height:1;opacity:0.7}.mrd-relation-field__tag-remove.sc-mrd-relation-field:hover{opacity:1}.mrd-relation-field__search-wrapper.sc-mrd-relation-field{position:relative;display:flex;align-items:center}.mrd-relation-field__search.sc-mrd-relation-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);outline:none;appearance:none;box-sizing:border-box}.mrd-relation-field__search.sc-mrd-relation-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-relation-field__search.sc-mrd-relation-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-relation-field__search.sc-mrd-relation-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-relation-field__search--error.sc-mrd-relation-field{border-color:var(--mrd-border-color-error)}.mrd-relation-field__search--error.sc-mrd-relation-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-relation-field__spinner.sc-mrd-relation-field{position:absolute;right:var(--mrd-space-3);width:16px;height:16px;border:2px solid var(--mrd-color-neutral-200);border-top-color:var(--mrd-color-primary);border-radius:50%;animation:mrd-spin 0.7s linear infinite}@keyframes mrd-spin{to{transform:rotate(360deg)}}.mrd-relation-field__results.sc-mrd-relation-field{position:absolute;top:calc(100% + var(--mrd-space-1));left:0;right:0;background-color:var(--mrd-color-white);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);box-shadow:var(--mrd-shadow-md);z-index:var(--mrd-z-dropdown);max-height:240px;overflow-y:auto}.mrd-relation-field__result-item.sc-mrd-relation-field{display:flex;flex-direction:column;padding:var(--mrd-space-2) var(--mrd-space-3);cursor:pointer;transition:background-color var(--mrd-transition-fast)}.mrd-relation-field__result-item.sc-mrd-relation-field:hover{background-color:var(--mrd-color-neutral-50)}.mrd-relation-field__result-item.sc-mrd-relation-field:not(:last-child){border-bottom:var(--mrd-border-width) solid var(--mrd-color-neutral-100)}.mrd-relation-field__result-label.sc-mrd-relation-field{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-color-neutral-800);font-weight:var(--mrd-font-weight-medium)}.mrd-relation-field__result-desc.sc-mrd-relation-field{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-500);margin-top:var(--mrd-space-1)}.mrd-relation-field__result-item--highlighted.sc-mrd-relation-field{background-color:var(--mrd-color-primary-light)}.mrd-relation-field__selected-value.sc-mrd-relation-field{display:flex;align-items:center;gap:var(--mrd-space-2);height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);background-color:var(--mrd-color-primary-light);border:var(--mrd-border-width) solid var(--mrd-color-primary);border-radius:var(--mrd-border-radius);box-sizing:border-box}.mrd-relation-field__selected-value--error.sc-mrd-relation-field{border-color:var(--mrd-border-color-error);background-color:var(--mrd-color-danger-light)}.mrd-relation-field__selected-name.sc-mrd-relation-field{flex:1;font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);font-weight:var(--mrd-font-weight-medium);color:var(--mrd-color-primary-dark);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mrd-relation-field__selected-clear.sc-mrd-relation-field{flex-shrink:0;background:none;border:none;cursor:pointer;color:var(--mrd-color-primary-dark);font-size:var(--mrd-font-size-sm);padding:0;line-height:1;opacity:0.6;transition:opacity var(--mrd-transition-fast)}.mrd-relation-field__selected-clear.sc-mrd-relation-field:hover{opacity:1}.mrd-relation-field__no-results.sc-mrd-relation-field{padding:var(--mrd-space-4);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-500);text-align:center}.mrd-relation-field__error.sc-mrd-relation-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}`;
3575
+ const mrdRelationFieldCss = () => `.sc-mrd-relation-field-h{display:block}.mrd-relation-field.sc-mrd-relation-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%;position:relative}.mrd-relation-field__label.sc-mrd-relation-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-relation-field__label--required.sc-mrd-relation-field::after{content:" *";color:var(--mrd-color-danger)}.mrd-relation-field__select.sc-mrd-relation-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box}.mrd-relation-field__select.sc-mrd-relation-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-relation-field__select.sc-mrd-relation-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-relation-field__select.sc-mrd-relation-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-relation-field__select--error.sc-mrd-relation-field{border-color:var(--mrd-border-color-error)}.mrd-relation-field__select--error.sc-mrd-relation-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-relation-field__select.sc-mrd-relation-field{background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%236b7280' stroke-width='2'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:right var(--mrd-space-3) center;padding-right:calc(var(--mrd-input-padding-x) + 1.5rem);cursor:pointer}.mrd-relation-field__search.sc-mrd-relation-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box}.mrd-relation-field__search.sc-mrd-relation-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-relation-field__search.sc-mrd-relation-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-relation-field__search.sc-mrd-relation-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-relation-field__search--error.sc-mrd-relation-field{border-color:var(--mrd-border-color-error)}.mrd-relation-field__search--error.sc-mrd-relation-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-relation-field__error.sc-mrd-relation-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}.mrd-relation-field__tags.sc-mrd-relation-field{display:flex;flex-wrap:wrap;gap:var(--mrd-space-1);margin-bottom:var(--mrd-space-1)}.mrd-relation-field__tag.sc-mrd-relation-field{display:inline-flex;align-items:center;gap:var(--mrd-space-1);padding:var(--mrd-space-1) var(--mrd-space-2);background-color:var(--mrd-color-primary-light);color:var(--mrd-color-primary-dark);border-radius:var(--mrd-border-radius-full);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);font-weight:var(--mrd-font-weight-medium)}.mrd-relation-field__tag-remove.sc-mrd-relation-field{background:none;border:none;cursor:pointer;color:var(--mrd-color-primary-dark);font-size:var(--mrd-font-size-xs);padding:0;line-height:1;opacity:0.7}.mrd-relation-field__tag-remove.sc-mrd-relation-field:hover{opacity:1}.mrd-relation-field__search-wrapper.sc-mrd-relation-field{position:relative;display:flex;align-items:center}.mrd-relation-field__spinner.sc-mrd-relation-field{position:absolute;right:var(--mrd-space-3);width:16px;height:16px;border:2px solid var(--mrd-color-neutral-200);border-top-color:var(--mrd-color-primary);border-radius:50%;animation:mrd-spin 0.7s linear infinite}@keyframes mrd-spin{to{transform:rotate(360deg)}}.mrd-relation-field__results.sc-mrd-relation-field{position:absolute;top:calc(100% + var(--mrd-space-1));left:0;right:0;background-color:var(--mrd-color-white);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);box-shadow:var(--mrd-shadow-md);z-index:var(--mrd-z-dropdown);max-height:240px;overflow-y:auto}.mrd-relation-field__result-item.sc-mrd-relation-field{display:flex;flex-direction:column;padding:var(--mrd-space-2) var(--mrd-space-3);cursor:pointer;transition:background-color var(--mrd-transition-fast)}.mrd-relation-field__result-item.sc-mrd-relation-field:hover{background-color:var(--mrd-color-neutral-50)}.mrd-relation-field__result-item.sc-mrd-relation-field:not(:last-child){border-bottom:var(--mrd-border-width) solid var(--mrd-color-neutral-100)}.mrd-relation-field__result-label.sc-mrd-relation-field{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-color-neutral-800);font-weight:var(--mrd-font-weight-medium)}.mrd-relation-field__result-desc.sc-mrd-relation-field{font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-500);margin-top:var(--mrd-space-1)}.mrd-relation-field__result-item--highlighted.sc-mrd-relation-field{background-color:var(--mrd-color-primary-light)}.mrd-relation-field__selected-value.sc-mrd-relation-field{display:flex;align-items:center;gap:var(--mrd-space-2);height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);background-color:var(--mrd-color-primary-light);border:var(--mrd-border-width) solid var(--mrd-color-primary);border-radius:var(--mrd-border-radius);box-sizing:border-box}.mrd-relation-field__selected-value--error.sc-mrd-relation-field{border-color:var(--mrd-border-color-error);background-color:var(--mrd-color-danger-light)}.mrd-relation-field__selected-name.sc-mrd-relation-field{flex:1;font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);font-weight:var(--mrd-font-weight-medium);color:var(--mrd-color-primary-dark);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mrd-relation-field__selected-clear.sc-mrd-relation-field{flex-shrink:0;background:none;border:none;cursor:pointer;color:var(--mrd-color-primary-dark);font-size:var(--mrd-font-size-sm);padding:0;line-height:1;opacity:0.6;transition:opacity var(--mrd-transition-fast)}.mrd-relation-field__selected-clear.sc-mrd-relation-field:hover{opacity:1}.mrd-relation-field__no-results.sc-mrd-relation-field{padding:var(--mrd-space-4);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-500);text-align:center}`;
3422
3576
 
3423
3577
  const MrdRelationField = class {
3424
3578
  constructor(hostRef) {
@@ -3519,12 +3673,7 @@ const MrdRelationField = class {
3519
3673
  this.showResults = false;
3520
3674
  this.mrdChange.emit({ name: this.name, value: result.id });
3521
3675
  }
3522
- if (this.required && !validateRequired(this.selectedItems)) {
3523
- this.error = t('required', this.locale);
3524
- }
3525
- else {
3526
- this.error = '';
3527
- }
3676
+ this.error = requiredError(this.selectedItems, this.required, this.locale);
3528
3677
  };
3529
3678
  this.handleRemoveSelected = (id) => {
3530
3679
  this.selectedItems = this.selectedItems.filter(i => i.id !== id);
@@ -3533,12 +3682,7 @@ const MrdRelationField = class {
3533
3682
  };
3534
3683
  this.handleDropdownChange = (e) => {
3535
3684
  const val = e.target.value;
3536
- if (this.required && !validateRequired(val)) {
3537
- this.error = t('required', this.locale);
3538
- }
3539
- else {
3540
- this.error = '';
3541
- }
3685
+ this.error = requiredError(val, this.required, this.locale);
3542
3686
  this.mrdChange.emit({ name: this.name, value: val });
3543
3687
  };
3544
3688
  this.handleBlur = () => {
@@ -3649,19 +3793,19 @@ const MrdRelationField = class {
3649
3793
  const hasError = !!this.error;
3650
3794
  if (this.editBehavior === index$1.ClientLayoutItemRelationEditBehavior.DROPDOWN) {
3651
3795
  const currentValue = this.getValueHref();
3652
- return (index.h(index.Host, null, index.h("div", { class: "mrd-relation-field" }, this.label && (index.h("label", { class: `mrd-relation-field__label${this.required ? ' mrd-relation-field__label--required' : ''}` }, this.label)), index.h("select", { class: `mrd-relation-field__select${hasError ? ' mrd-relation-field__select--error' : ''}`, name: this.name, required: this.required, disabled: this.disabled, onChange: this.handleDropdownChange }, index.h("option", { value: "" }, t('select_placeholder', this.locale)), this.allRecords.map(record => (index.h("option", { key: record.id, value: record.id, selected: record.id === currentValue }, record.label)))), hasError && index.h("span", { class: "mrd-relation-field__error" }, this.error))));
3796
+ return (index.h(index.Host, null, index.h("div", { class: "mrd-relation-field" }, index.h(FieldLabel, { base: "mrd-relation-field", label: this.label, required: this.required }), index.h("select", { class: controlClass('mrd-relation-field', hasError, 'select'), name: this.name, required: this.required, disabled: this.disabled, onChange: this.handleDropdownChange }, index.h("option", { value: "" }, t('select_placeholder', this.locale)), this.allRecords.map(record => (index.h("option", { key: record.id, value: record.id, selected: record.id === currentValue }, record.label)))), index.h(FieldError, { base: "mrd-relation-field", error: this.error }))));
3653
3797
  }
3654
3798
  if (this.displayType === index$1.ClientLayoutItemRelationDisplayType.DROPDOWN) {
3655
3799
  const currentValue = Array.isArray(this.value) ? ((_a = this.value[0]) !== null && _a !== void 0 ? _a : '') : ((_b = this.value) !== null && _b !== void 0 ? _b : '');
3656
- return (index.h(index.Host, null, index.h("div", { class: "mrd-relation-field" }, this.label && (index.h("label", { class: `mrd-relation-field__label${this.required ? ' mrd-relation-field__label--required' : ''}` }, this.label)), index.h("select", { class: `mrd-relation-field__select${hasError ? ' mrd-relation-field__select--error' : ''}`, name: this.name, required: this.required, disabled: this.disabled, onChange: this.handleDropdownChange }, index.h("option", { value: "" }, t('select_placeholder', this.locale)), this.dropdownValues.map(dv => (index.h("option", { key: dv.key, value: dv.key, selected: dv.key === currentValue }, dv.label)))), hasError && index.h("span", { class: "mrd-relation-field__error" }, this.error))));
3800
+ return (index.h(index.Host, null, index.h("div", { class: "mrd-relation-field" }, index.h(FieldLabel, { base: "mrd-relation-field", label: this.label, required: this.required }), index.h("select", { class: controlClass('mrd-relation-field', hasError, 'select'), name: this.name, required: this.required, disabled: this.disabled, onChange: this.handleDropdownChange }, index.h("option", { value: "" }, t('select_placeholder', this.locale)), this.dropdownValues.map(dv => (index.h("option", { key: dv.key, value: dv.key, selected: dv.key === currentValue }, dv.label)))), index.h(FieldError, { base: "mrd-relation-field", error: this.error }))));
3657
3801
  }
3658
3802
  // SEARCH mode
3659
- const labelEl = this.label && (index.h("label", { class: `mrd-relation-field__label${this.required ? ' mrd-relation-field__label--required' : ''}` }, this.label));
3803
+ const labelEl = index.h(FieldLabel, { base: "mrd-relation-field", label: this.label, required: this.required });
3660
3804
  // Single selection: show selected value as a badge, hide the search input
3661
3805
  if (!this.multiple && this.selectedItems.length > 0) {
3662
- return (index.h(index.Host, null, index.h("div", { class: "mrd-relation-field" }, labelEl, index.h("div", { class: `mrd-relation-field__selected-value${hasError ? ' mrd-relation-field__selected-value--error' : ''}` }, index.h("span", { class: "mrd-relation-field__selected-name" }, this.selectedItems[0].label), index.h("button", { type: "button", class: "mrd-relation-field__selected-clear", onClick: this.clearSelection, "aria-label": t('remove', this.locale) }, "\u2715")), hasError && index.h("span", { class: "mrd-relation-field__error" }, this.error))));
3806
+ return (index.h(index.Host, null, index.h("div", { class: "mrd-relation-field" }, labelEl, index.h("div", { class: `mrd-relation-field__selected-value${hasError ? ' mrd-relation-field__selected-value--error' : ''}` }, index.h("span", { class: "mrd-relation-field__selected-name" }, this.selectedItems[0].label), index.h("button", { type: "button", class: "mrd-relation-field__selected-clear", onClick: this.clearSelection, "aria-label": t('remove', this.locale) }, "\u2715")), index.h(FieldError, { base: "mrd-relation-field", error: this.error }))));
3663
3807
  }
3664
- return (index.h(index.Host, null, index.h("div", { class: "mrd-relation-field" }, labelEl, this.multiple && this.selectedItems.length > 0 && (index.h("div", { class: "mrd-relation-field__tags" }, this.selectedItems.map(item => (index.h("span", { key: item.id, class: "mrd-relation-field__tag" }, item.label, index.h("button", { type: "button", class: "mrd-relation-field__tag-remove", onClick: () => this.handleRemoveSelected(item.id), "aria-label": t('remove', this.locale) }, "\u2715")))))), index.h("div", { class: "mrd-relation-field__search-wrapper" }, index.h("input", { class: `mrd-relation-field__search${hasError ? ' mrd-relation-field__search--error' : ''}`, type: "text", value: this.searchQuery, placeholder: t('search_placeholder', this.locale), disabled: this.disabled, onInput: this.handleSearchInput, onKeyDown: this.handleKeyDown, onBlur: this.handleBlur }), this.isLoading && (index.h("span", { class: "mrd-relation-field__spinner", "aria-label": t('loading', this.locale) }))), this.showResults && (index.h("div", { class: "mrd-relation-field__results" }, this.searchResults.length === 0 && !this.isLoading ? (index.h("div", { class: "mrd-relation-field__no-results" }, t('no_results', this.locale))) : (this.searchResults.map((result, i) => (index.h("div", { key: result.id, class: `mrd-relation-field__result-item${i === this.highlightedIndex ? ' mrd-relation-field__result-item--highlighted' : ''}`, onMouseDown: () => this.handleResultSelect(result) }, index.h("span", { class: "mrd-relation-field__result-label" }, result.label), result.description && (index.h("span", { class: "mrd-relation-field__result-desc" }, result.description)))))))), hasError && index.h("span", { class: "mrd-relation-field__error" }, this.error))));
3808
+ return (index.h(index.Host, null, index.h("div", { class: "mrd-relation-field" }, labelEl, this.multiple && this.selectedItems.length > 0 && (index.h("div", { class: "mrd-relation-field__tags" }, this.selectedItems.map(item => (index.h("span", { key: item.id, class: "mrd-relation-field__tag" }, item.label, index.h("button", { type: "button", class: "mrd-relation-field__tag-remove", onClick: () => this.handleRemoveSelected(item.id), "aria-label": t('remove', this.locale) }, "\u2715")))))), index.h("div", { class: "mrd-relation-field__search-wrapper" }, index.h("input", { class: `mrd-relation-field__search${hasError ? ' mrd-relation-field__search--error' : ''}`, type: "text", value: this.searchQuery, placeholder: t('search_placeholder', this.locale), disabled: this.disabled, onInput: this.handleSearchInput, onKeyDown: this.handleKeyDown, onBlur: this.handleBlur }), this.isLoading && (index.h("span", { class: "mrd-relation-field__spinner", "aria-label": t('loading', this.locale) }))), this.showResults && (index.h("div", { class: "mrd-relation-field__results" }, this.searchResults.length === 0 && !this.isLoading ? (index.h("div", { class: "mrd-relation-field__no-results" }, t('no_results', this.locale))) : (this.searchResults.map((result, i) => (index.h("div", { key: result.id, class: `mrd-relation-field__result-item${i === this.highlightedIndex ? ' mrd-relation-field__result-item--highlighted' : ''}`, onMouseDown: () => this.handleResultSelect(result) }, index.h("span", { class: "mrd-relation-field__result-label" }, result.label), result.description && (index.h("span", { class: "mrd-relation-field__result-desc" }, result.description)))))))), index.h(FieldError, { base: "mrd-relation-field", error: this.error }))));
3665
3809
  }
3666
3810
  get el() { return index.getElement(this); }
3667
3811
  static get watchers() { return {
@@ -3673,9 +3817,9 @@ const MrdRelationField = class {
3673
3817
  }]
3674
3818
  }; }
3675
3819
  };
3676
- MrdRelationField.style = mrdRelationFieldScss();
3820
+ MrdRelationField.style = mrdRelationFieldCss();
3677
3821
 
3678
- const mrdSecretFieldScss = () => `.sc-mrd-secret-field-h{display:block}.mrd-secret-field.sc-mrd-secret-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-secret-field__label.sc-mrd-secret-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-secret-field__label--required.sc-mrd-secret-field::after{content:' *';color:var(--mrd-color-danger)}.mrd-secret-field__input.sc-mrd-secret-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box}.mrd-secret-field__input.sc-mrd-secret-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-secret-field__input.sc-mrd-secret-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-secret-field__input--error.sc-mrd-secret-field{border-color:var(--mrd-border-color-error)}.mrd-secret-field__input--error.sc-mrd-secret-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-secret-field__error.sc-mrd-secret-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}.mrd-secret-field__masked.sc-mrd-secret-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-label-color);letter-spacing:0.15em;user-select:none;pointer-events:none}`;
3822
+ const mrdSecretFieldCss = () => `.sc-mrd-secret-field-h{display:block}.mrd-secret-field.sc-mrd-secret-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-secret-field__label.sc-mrd-secret-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-secret-field__label--required.sc-mrd-secret-field::after{content:" *";color:var(--mrd-color-danger)}.mrd-secret-field__input.sc-mrd-secret-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box}.mrd-secret-field__input.sc-mrd-secret-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-secret-field__input.sc-mrd-secret-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-secret-field__input.sc-mrd-secret-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-secret-field__input--error.sc-mrd-secret-field{border-color:var(--mrd-border-color-error)}.mrd-secret-field__input--error.sc-mrd-secret-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-secret-field__error.sc-mrd-secret-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}.mrd-secret-field__masked.sc-mrd-secret-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-label-color);letter-spacing:0.15em;user-select:none;pointer-events:none}`;
3679
3823
 
3680
3824
  const MrdSecretField = class {
3681
3825
  constructor(hostRef) {
@@ -3696,38 +3840,439 @@ const MrdSecretField = class {
3696
3840
  };
3697
3841
  this.handleBlur = (e) => {
3698
3842
  const val = e.target.value;
3699
- if (this.required && !validateRequired(val)) {
3700
- this.error = t('required', this.locale);
3701
- }
3702
- else {
3703
- this.error = '';
3704
- }
3843
+ this.error = requiredError(val, this.required, this.locale);
3705
3844
  this.mrdBlur.emit({ name: this.name, value: val });
3706
3845
  };
3707
3846
  }
3708
3847
  render() {
3709
- const hasError = !!this.error;
3710
- return (index.h(index.Host, { key: 'c850ec5bc5967ca0aefca7d7cb65ecae121a9dc1' }, index.h("div", { key: '3249ffbc441422af054a20806dd8dfce954a8ffc', class: "mrd-secret-field" }, this.label && (index.h("label", { key: '0b4a86da9cafad32f153af1bc5487a4e9b941e2f', class: `mrd-secret-field__label${this.required ? ' mrd-secret-field__label--required' : ''}` }, this.label)), this.disabled
3848
+ return (index.h(index.Host, { key: 'acb865b235652feba713aedda7a7fccbdc01ad20' }, index.h("div", { key: 'e7471ade9c683cac9469ec89778c967badb046f9', class: "mrd-secret-field" }, index.h(FieldLabel, { key: '2f9b864779ead352fda53af8597ddcd31377249d', base: "mrd-secret-field", label: this.label, required: this.required }), this.disabled
3711
3849
  ? (index.h("span", { class: "mrd-secret-field__masked", "aria-label": this.label }, this.value ? '••••••••' : ''))
3712
- : (index.h("input", { class: `mrd-secret-field__input${hasError ? ' mrd-secret-field__input--error' : ''}`, type: "password", name: this.name, value: this.value, placeholder: this.placeholder, required: this.required, autocomplete: "new-password", onInput: this.handleInput, onBlur: this.handleBlur })), hasError && index.h("span", { key: 'b0d0105f3d43d2e214f070b24e745dbce0e33977', class: "mrd-secret-field__error" }, this.error))));
3850
+ : (index.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 })), index.h(FieldError, { key: '438418e2cf0f53a6c247d5f332aae8e8978b94ea', base: "mrd-secret-field", error: this.error }))));
3713
3851
  }
3714
3852
  };
3715
- MrdSecretField.style = mrdSecretFieldScss();
3716
-
3717
- const mrdTableScss = () => `.sc-mrd-table-h{display:block;width:100%}.mrd-table__scroll.sc-mrd-table{overflow-y:auto;overflow-x:auto;border:1px solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);overflow-anchor:none}.mrd-table.sc-mrd-table{overflow-x:auto}.mrd-table__table.sc-mrd-table{width:auto;min-width:100%;border-collapse:collapse;font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-900)}.mrd-table__scroll.sc-mrd-table .mrd-table__table.sc-mrd-table{min-width:max-content}.mrd-table__header.sc-mrd-table{position:sticky;top:0;z-index:1;background:var(--mrd-color-white);text-align:left;padding:var(--mrd-space-2) var(--mrd-space-4);border-bottom:2px solid var(--mrd-border-color);color:var(--mrd-color-neutral-600);font-weight:var(--mrd-font-weight-medium);white-space:nowrap;font-size:var(--mrd-font-size-xs);text-transform:uppercase;letter-spacing:0.04em}.mrd-table__header--sortable.sc-mrd-table{cursor:pointer;user-select:none}.mrd-table__header--sortable.sc-mrd-table:hover{background:var(--mrd-color-neutral-50);color:var(--mrd-color-neutral-800)}.mrd-table__header--sorted-asc.sc-mrd-table,.mrd-table__header--sorted-desc.sc-mrd-table{color:var(--mrd-color-primary);border-bottom-color:var(--mrd-color-primary)}.mrd-table__header-label.sc-mrd-table{margin-right:var(--mrd-space-1)}.mrd-table__sort-icon.sc-mrd-table{font-size:0.85rem;opacity:0.4;vertical-align:middle}.mrd-table__header--sorted-asc.sc-mrd-table .mrd-table__sort-icon.sc-mrd-table,.mrd-table__header--sorted-desc.sc-mrd-table .mrd-table__sort-icon.sc-mrd-table{opacity:1;color:var(--mrd-color-primary)}.mrd-table__filter-icon.sc-mrd-table{display:inline-flex;align-items:center;vertical-align:middle;margin-left:var(--mrd-space-1);color:var(--mrd-color-primary)}.mrd-table__row.sc-mrd-table{border-bottom:1px solid var(--mrd-border-color)}.mrd-table__row.sc-mrd-table:hover{background:var(--mrd-color-neutral-200) !important}.mrd-table__row--clickable.sc-mrd-table{cursor:pointer}.mrd-table__spacer.sc-mrd-table{border:none}.mrd-table__spacer.sc-mrd-table td.sc-mrd-table{padding:0;border:none}.mrd-table__cell.sc-mrd-table{padding:var(--mrd-space-2) var(--mrd-space-4);vertical-align:top;white-space:nowrap}.mrd-table__cell--numeric.sc-mrd-table{text-align:right;font-variant-numeric:tabular-nums}.mrd-table__row--loading.sc-mrd-table{background:transparent}.mrd-table__cell--placeholder.sc-mrd-table{padding:var(--mrd-space-2) var(--mrd-space-4);border-bottom:1px solid var(--mrd-border-color)}.mrd-table__placeholder-bar.sc-mrd-table{display:block;height:0.75rem;width:55%;border-radius:var(--mrd-border-radius-sm);background:linear-gradient( 90deg, var(--mrd-color-neutral-200) 25%, var(--mrd-color-neutral-100) 50%, var(--mrd-color-neutral-200) 75% );background-size:200% 100%;animation:mrd-shimmer 1.4s ease infinite}@keyframes mrd-shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}.mrd-table__toolbar.sc-mrd-table{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--mrd-space-2)}.mrd-table__toolbar-left.sc-mrd-table,.mrd-table__toolbar-right.sc-mrd-table{display:flex;gap:var(--mrd-space-2);align-items:center}.mrd-table__toolbar-center.sc-mrd-table{flex:1;display:flex;justify-content:center;align-items:center;gap:var(--mrd-space-1)}.mrd-table__view-switcher.sc-mrd-table{display:flex;align-items:center;gap:var(--mrd-space-1)}.mrd-table__view-arrow.sc-mrd-table{background:none;border:none;cursor:pointer;padding:0 var(--mrd-space-1);color:var(--mrd-color-neutral-500);font-size:var(--mrd-font-size-xs);line-height:1}.mrd-table__view-arrow.sc-mrd-table:hover{color:var(--mrd-color-neutral-800)}.mrd-table__view-title-wrap.sc-mrd-table{position:relative}.mrd-table__view-title.sc-mrd-table{font-size:var(--mrd-font-size-sm);font-weight:600;color:var(--mrd-color-neutral-800);font-family:var(--mrd-font-family);background:none;border:none;outline:none;cursor:pointer;padding:0 var(--mrd-space-1);max-width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mrd-table__view-title.sc-mrd-table:hover{color:var(--mrd-color-primary)}.mrd-table__view-popover.sc-mrd-table{position:absolute;top:calc(100% + var(--mrd-space-1));left:50%;transform:translateX(-50%);background:var(--mrd-color-white);border:1px solid var(--mrd-color-neutral-200);border-radius:var(--mrd-radius-md);box-shadow:var(--mrd-shadow-md);z-index:100;min-width:160px;padding:var(--mrd-space-1) 0}.mrd-table__view-popover-item.sc-mrd-table{display:block;width:100%;text-align:left;background:none;border:none;cursor:pointer;padding:var(--mrd-space-2) var(--mrd-space-3);font-size:var(--mrd-font-size-sm);font-family:var(--mrd-font-family);color:var(--mrd-color-neutral-700);white-space:nowrap}.mrd-table__view-popover-item.sc-mrd-table:hover{background:var(--mrd-color-neutral-50)}.mrd-table__view-popover-item--active.sc-mrd-table{font-weight:600;color:var(--mrd-color-primary)}.mrd-table__action.sc-mrd-table{position:relative;display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;background:transparent;border:1px solid transparent;border-radius:var(--mrd-border-radius);cursor:pointer;color:var(--mrd-color-neutral-400);transition:background-color 0.15s, border-color 0.15s, color 0.15s}.mrd-table__action.sc-mrd-table:hover{background-color:var(--mrd-color-neutral-100);border-color:var(--mrd-color-neutral-300);color:var(--mrd-color-neutral-700)}.mrd-table__action.sc-mrd-table:disabled{opacity:0.4;cursor:not-allowed}.mrd-table__action--primary.sc-mrd-table{color:var(--mrd-color-neutral-500)}.mrd-table__action--primary.sc-mrd-table:hover{background:var(--mrd-color-primary);border-color:var(--mrd-color-primary);color:var(--mrd-color-white)}.mrd-table__action--danger.sc-mrd-table{color:var(--mrd-color-error)}.mrd-table__action--danger.sc-mrd-table:hover{background-color:var(--mrd-color-error-light, #fef2f2);border-color:var(--mrd-color-error)}.mrd-table__action-icon.sc-mrd-table{width:1.25rem;height:1.25rem;pointer-events:none;fill:currentColor}.mrd-table__action-tooltip.sc-mrd-table{display:none;position:absolute;bottom:calc(100% + 6px);right:0;padding:var(--mrd-space-1) var(--mrd-space-2);font-size:var(--mrd-font-size-xs);white-space:nowrap;background:var(--mrd-color-tooltip, #fffce1);color:var(--mrd-color-neutral-900);border:1px solid var(--mrd-border-color);border-radius:var(--mrd-border-radius-sm, var(--mrd-border-radius));pointer-events:none;z-index:10}.mrd-table__action.sc-mrd-table:hover .mrd-table__action-tooltip.sc-mrd-table{display:block}.mrd-table__create-picker-wrap.sc-mrd-table{position:relative}.mrd-table__create-picker.sc-mrd-table{position:absolute;right:0;top:calc(100% + 4px);background:var(--mrd-color-white, #fff);border:1px solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);box-shadow:var(--mrd-shadow-md, 0 4px 12px rgba(0, 0, 0, 0.12));z-index:10;min-width:10rem;padding:var(--mrd-space-1) 0}.mrd-table__create-picker-item.sc-mrd-table{display:block;width:100%;text-align:left;padding:var(--mrd-space-2) var(--mrd-space-3);background:none;border:none;cursor:pointer;font-size:var(--mrd-font-size-sm);font-family:var(--mrd-font-family);color:var(--mrd-color-neutral-800)}.mrd-table__create-picker-item.sc-mrd-table:hover{background:var(--mrd-color-neutral-50);color:var(--mrd-color-neutral-900)}.mrd-table__filter-toggle--active.sc-mrd-table{background:var(--mrd-color-primary);border-color:var(--mrd-color-primary);color:var(--mrd-color-white)}.mrd-table__filter-toggle--active.sc-mrd-table:hover{background:var(--mrd-color-primary-dark, var(--mrd-color-primary));border-color:var(--mrd-color-primary-dark, var(--mrd-color-primary));color:var(--mrd-color-white)}.mrd-table__filter-badge.sc-mrd-table{position:absolute;top:-6px;right:-6px;min-width:1.25rem;height:1.25rem;padding:0 3px;background:var(--mrd-color-error, #e53e3e);color:var(--mrd-color-white);border-radius:9999px;font-size:0.65rem;font-weight:var(--mrd-font-weight-medium);line-height:1.25rem;text-align:center;pointer-events:none}.mrd-table__header--filtered.sc-mrd-table{color:var(--mrd-color-primary);border-bottom-color:var(--mrd-color-primary)}.mrd-table__filter-popup.sc-mrd-table{position:fixed;width:280px;background:var(--mrd-color-white);border:1px solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);box-shadow:var(--mrd-shadow-md, 0 4px 12px rgba(0,0,0,.12));z-index:var(--mrd-z-dropdown, 200);font-size:var(--mrd-font-size-sm)}.mrd-table__filter-popup-header.sc-mrd-table{display:flex;align-items:center;justify-content:space-between;padding:var(--mrd-space-2) var(--mrd-space-3);border-bottom:1px solid var(--mrd-border-color)}.mrd-table__filter-popup-title.sc-mrd-table{font-weight:var(--mrd-font-weight-medium);color:var(--mrd-color-neutral-800);font-size:var(--mrd-font-size-sm)}.mrd-table__filter-close.sc-mrd-table{background:transparent;border:none;cursor:pointer;color:var(--mrd-color-neutral-500);font-size:0.9rem;padding:2px 4px;border-radius:3px;line-height:1}.mrd-table__filter-close.sc-mrd-table:hover{background:var(--mrd-color-neutral-100);color:var(--mrd-color-neutral-800)}.mrd-table__filter-section.sc-mrd-table{padding:var(--mrd-space-2) var(--mrd-space-3)}.mrd-table__filter-section-label.sc-mrd-table{font-size:var(--mrd-font-size-xs);font-weight:var(--mrd-font-weight-medium);text-transform:uppercase;letter-spacing:0.04em;color:var(--mrd-color-neutral-500);margin-bottom:var(--mrd-space-2)}.mrd-table__filter-sort-buttons.sc-mrd-table{display:flex;gap:var(--mrd-space-2)}.mrd-table__filter-sort-btn.sc-mrd-table{flex:1;padding:var(--mrd-space-1) var(--mrd-space-2);background:transparent;border:1px solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);cursor:pointer;font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-700)}.mrd-table__filter-sort-btn.sc-mrd-table:hover{background:var(--mrd-color-neutral-100)}.mrd-table__filter-sort-btn--active.sc-mrd-table{background:var(--mrd-color-primary);border-color:var(--mrd-color-primary);color:var(--mrd-color-white)}.mrd-table__filter-divider.sc-mrd-table{height:1px;background:var(--mrd-border-color);margin:0}.mrd-table__filter-editor.sc-mrd-table{display:flex;flex-direction:column;gap:var(--mrd-space-2)}.mrd-table__filter-select.sc-mrd-table,.mrd-table__filter-input.sc-mrd-table{width:100%;padding:var(--mrd-space-1) var(--mrd-space-2);border:1px solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-900);background:var(--mrd-color-white);box-sizing:border-box}.mrd-table__filter-select.sc-mrd-table:focus,.mrd-table__filter-input.sc-mrd-table:focus{outline:none;border-color:var(--mrd-color-primary);box-shadow:0 0 0 2px rgba(0,0,0,.06)}.mrd-table__filter-range.sc-mrd-table{display:flex;align-items:center;gap:var(--mrd-space-1)}.mrd-table__filter-range.sc-mrd-table .mrd-table__filter-input.sc-mrd-table{flex:1;min-width:0}.mrd-table__filter-range-sep.sc-mrd-table{color:var(--mrd-color-neutral-400);flex-shrink:0}.mrd-table__filter-range--stacked.sc-mrd-table{flex-direction:column;align-items:stretch;gap:var(--mrd-space-2)}.mrd-table__filter-range-label.sc-mrd-table{font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-500);margin-bottom:2px}.mrd-table__filter-radio-group.sc-mrd-table{display:flex;flex-direction:column;gap:var(--mrd-space-1)}.mrd-table__filter-radio-group--inline.sc-mrd-table{flex-direction:row;gap:var(--mrd-space-3)}.mrd-table__filter-radio-label.sc-mrd-table{display:flex;align-items:center;gap:var(--mrd-space-1);cursor:pointer;font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-800)}.mrd-table__filter-list.sc-mrd-table{display:flex;flex-direction:column;gap:var(--mrd-space-1);max-height:180px;overflow-y:auto}.mrd-table__filter-list-controls.sc-mrd-table{display:flex;gap:var(--mrd-space-2);margin-bottom:var(--mrd-space-1)}.mrd-table__filter-list-btn.sc-mrd-table{font-size:var(--mrd-font-size-xs);color:var(--mrd-color-primary);background:transparent;border:none;cursor:pointer;padding:0;text-decoration:underline}.mrd-table__filter-checkbox-label.sc-mrd-table{display:flex;align-items:center;gap:var(--mrd-space-1);cursor:pointer;font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-800)}.mrd-table__filter-no-support.sc-mrd-table{font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-500);margin:0;font-style:italic}.mrd-table__filter-popup-footer.sc-mrd-table{display:flex;justify-content:flex-end;gap:var(--mrd-space-2);padding:var(--mrd-space-2) var(--mrd-space-3);border-top:1px solid var(--mrd-border-color)}.mrd-table__filter-btn.sc-mrd-table{padding:var(--mrd-space-1) var(--mrd-space-3);border-radius:var(--mrd-border-radius);border:1px solid var(--mrd-border-color);font-size:var(--mrd-font-size-sm);cursor:pointer}.mrd-table__filter-btn--clear.sc-mrd-table{background:transparent;color:var(--mrd-color-neutral-600)}.mrd-table__filter-btn--clear.sc-mrd-table:hover{background:var(--mrd-color-neutral-100)}.mrd-table__filter-btn--apply.sc-mrd-table{background:var(--mrd-color-primary);border-color:var(--mrd-color-primary);color:var(--mrd-color-white)}.mrd-table__filter-btn--apply.sc-mrd-table:hover{background:var(--mrd-color-primary-dark, var(--mrd-color-primary));border-color:var(--mrd-color-primary-dark, var(--mrd-color-primary))}.mrd-table__totals-row.sc-mrd-table{border-top:2px solid var(--mrd-border-color)}.mrd-table__totals-cell.sc-mrd-table{position:sticky;bottom:0;z-index:2;padding:var(--mrd-space-2) var(--mrd-space-4);background:var(--mrd-color-white);font-weight:var(--mrd-font-weight-medium);font-variant-numeric:tabular-nums;white-space:nowrap;border-top:2px solid var(--mrd-border-color)}.mrd-table__totals-cell--numeric.sc-mrd-table{text-align:right}.mrd-table__footer.sc-mrd-table{padding:var(--mrd-space-1) var(--mrd-space-2);font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-500);text-align:right}.mrd-table__empty.sc-mrd-table{padding:var(--mrd-space-4) var(--mrd-space-3);color:var(--mrd-color-neutral-500);font-size:var(--mrd-font-size-sm);text-align:center;margin:0}.mrd-table__file-btn.sc-mrd-table{display:inline-flex;align-items:center;gap:var(--mrd-space-1);background:none;border:none;padding:0;cursor:pointer;color:var(--mrd-color-primary);font-size:var(--mrd-font-size-sm);font-family:inherit;max-width:100%;overflow:hidden}.mrd-table__file-btn.sc-mrd-table:hover{text-decoration:underline;color:var(--mrd-color-primary-dark)}.mrd-table__file-icon.sc-mrd-table{flex-shrink:0;width:1rem;height:1rem}.mrd-table__textblock-btn.sc-mrd-table{display:inline;background:none;border:none;padding:0 0 0 var(--mrd-space-1);cursor:pointer;color:var(--mrd-color-primary);font-size:var(--mrd-font-size-sm);font-family:inherit;line-height:inherit;vertical-align:middle}.mrd-table__textblock-btn.sc-mrd-table:hover{color:var(--mrd-color-primary-dark)}.mrd-table__modal-backdrop.sc-mrd-table{position:fixed;inset:0;background:rgba(0, 0, 0, 0.4);z-index:var(--mrd-z-modal, 300);display:flex;align-items:center;justify-content:center}.mrd-table__modal.sc-mrd-table{background:#fff;border-radius:var(--mrd-radius-md, 0.5rem);padding:var(--mrd-space-6);max-width:min(600px, 90vw);max-height:70vh;overflow-y:auto;position:relative;box-shadow:var(--mrd-shadow-lg)}.mrd-table__modal-close.sc-mrd-table{position:absolute;top:var(--mrd-space-3);right:var(--mrd-space-3);background:none;border:none;cursor:pointer;font-size:1.25rem;line-height:1;color:var(--mrd-color-text-muted, #6b7280);padding:0}.mrd-table__modal-close.sc-mrd-table:hover{color:var(--mrd-color-text, #111827)}.mrd-table__modal-text.sc-mrd-table{margin:0;padding-right:var(--mrd-space-6);white-space:pre-wrap;word-break:break-word;font-size:var(--mrd-font-size-sm);line-height:1.6}.mrd-table__json-preview.sc-mrd-table{font-family:var(--mrd-font-family-mono);font-size:var(--mrd-font-size-xs);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;display:inline-block;max-width:calc(100% - 1.5rem);vertical-align:middle}.mrd-table__modal-json.sc-mrd-table{margin:0;padding-right:var(--mrd-space-6);font-family:var(--mrd-font-family-mono);font-size:var(--mrd-font-size-xs);white-space:pre-wrap;word-break:break-word;line-height:1.6;background:none;border:none}`;
3853
+ MrdSecretField.style = mrdSecretFieldCss();
3718
3854
 
3719
- const BUFFER = 10;
3720
- /** Wacht deze tijd (ms) na het laatste scroll-event voordat pagina's worden
3721
- * aangevraagd. Pagina's die de gebruiker snel voorbij scrollt worden zo geskipt. */
3722
- const REQUEST_DEBOUNCE_MS = 150;
3723
- /** Breedte van de filterpopup in px — voor overflow-correctie. */
3724
- const POPUP_WIDTH = 280;
3855
+ /**
3856
+ * Pure sort/filter/aggregation query logic for mrd-table.
3857
+ * No component state everything is passed in.
3858
+ */
3725
3859
  const TEXT_TYPES = new Set(['TEXT', 'TEXTBLOCK', 'EMAIL', 'HYPERLINK']);
3726
3860
  const NUMERIC_TYPES = new Set(['INTEGER', 'DECIMAL', 'PERCENTAGE', 'CURRENCY']);
3727
3861
  const DATE_TYPES = new Set(['DATE', 'DATETIME', 'TIME']);
3728
3862
  const NO_FILTER_TYPES = new Set(['FILE', 'IMAGE']);
3729
3863
  /** Column types that cannot be sorted or filtered (not stored in PostgreSQL). */
3730
3864
  const NON_INTERACTIVE_TYPES = new Set(['LONGTEXT', 'JSON', 'FILE', 'IMAGE']);
3865
+ function parseDefaultSort(defaultSort) {
3866
+ var _a;
3867
+ if (!defaultSort)
3868
+ return { field: '', dir: 'asc' };
3869
+ const parts = defaultSort.split(',');
3870
+ return { field: parts[0].trim(), dir: ((_a = parts[1]) === null || _a === void 0 ? void 0 : _a.trim()) === 'desc' ? 'desc' : 'asc' };
3871
+ }
3872
+ /** Raw sort query-param value, e.g. "name" or "name,desc". */
3873
+ function buildSortParam(field, dir) {
3874
+ if (!field)
3875
+ return '';
3876
+ return dir === 'desc' ? `${field},desc` : field;
3877
+ }
3878
+ /** Query params for a page request: page + sort + filterClass + view filters + active column filters. */
3879
+ function buildTableQueryParams(opts) {
3880
+ var _a, _b;
3881
+ const p = new URLSearchParams();
3882
+ if (opts.page > 0)
3883
+ p.set('page', String(opts.page));
3884
+ if (opts.sort)
3885
+ p.set('sort', opts.sort);
3886
+ if (opts.filterClass)
3887
+ p.set('type', opts.filterClass);
3888
+ applyViewFilters(p, opts.viewFilters);
3889
+ for (const f of opts.activeFilters) {
3890
+ if (f.operator === 'isEmpty') {
3891
+ p.set(f.field, '');
3892
+ continue;
3893
+ }
3894
+ if (f.operator === 'isNotEmpty') {
3895
+ p.set(f.field + '_notempty', 'true');
3896
+ continue;
3897
+ }
3898
+ if (f.operator === 'startsWith') {
3899
+ p.set(f.field + '_startswith', String((_a = f.value) !== null && _a !== void 0 ? _a : ''));
3900
+ continue;
3901
+ }
3902
+ if ((_b = f.values) === null || _b === void 0 ? void 0 : _b.length) {
3903
+ p.set(f.field, f.values.join(','));
3904
+ continue;
3905
+ }
3906
+ if (f.value != null)
3907
+ p.set(f.field, String(f.value));
3908
+ if (f.from != null)
3909
+ p.set(f.field + '_from', String(f.from));
3910
+ if (f.to != null)
3911
+ p.set(f.field + '_to', String(f.to));
3912
+ }
3913
+ return p.toString();
3914
+ }
3915
+ /** Groups aggregate columns by function; null when the view has no aggregates. */
3916
+ function buildAggregationParams(columns) {
3917
+ var _a;
3918
+ const groups = { sum: [], avg: [], count: [] };
3919
+ for (const col of columns) {
3920
+ if (col.type !== 'FIELD' || !col.aggregate)
3921
+ continue;
3922
+ const fn = col.aggregate.toLowerCase();
3923
+ if (fn in groups)
3924
+ groups[fn].push((_a = col.name) !== null && _a !== void 0 ? _a : '');
3925
+ }
3926
+ const params = {};
3927
+ if (groups.sum.length)
3928
+ params.sum = groups.sum;
3929
+ if (groups.avg.length)
3930
+ params.avg = groups.avg;
3931
+ if (groups.count.length)
3932
+ params.count = groups.count;
3933
+ return Object.keys(params).length > 0 ? params : null;
3934
+ }
3935
+ /** Aggregation query string: the page-0 query params without page/sort, plus sum/avg/count. */
3936
+ function buildAggregationQs(basePageQs, columns) {
3937
+ var _a, _b, _c;
3938
+ const p = new URLSearchParams(basePageQs);
3939
+ p.delete('page');
3940
+ p.delete('sort');
3941
+ const groups = buildAggregationParams(columns);
3942
+ if ((_a = groups === null || groups === void 0 ? void 0 : groups.sum) === null || _a === void 0 ? void 0 : _a.length)
3943
+ p.set('sum', groups.sum.join(','));
3944
+ if ((_b = groups === null || groups === void 0 ? void 0 : groups.avg) === null || _b === void 0 ? void 0 : _b.length)
3945
+ p.set('avg', groups.avg.join(','));
3946
+ if ((_c = groups === null || groups === void 0 ? void 0 : groups.count) === null || _c === void 0 ? void 0 : _c.length)
3947
+ p.set('count', groups.count.join(','));
3948
+ return p.toString();
3949
+ }
3950
+ /** True when the pending filter actually constrains anything. */
3951
+ function filterHasValue(f) {
3952
+ if (f.operator === 'isEmpty' || f.operator === 'isNotEmpty')
3953
+ return true;
3954
+ if (f.values !== undefined && f.values.length > 0)
3955
+ return true;
3956
+ if (f.value != null && f.value !== '')
3957
+ return true;
3958
+ if (typeof f.value === 'boolean')
3959
+ return true;
3960
+ if (f.from != null && f.from !== '')
3961
+ return true;
3962
+ if (f.to != null && f.to !== '')
3963
+ return true;
3964
+ return false;
3965
+ }
3966
+ // ── DATETIME filters: the user edits local "YYYY-MM-DD" dates, the API stores UTC ISO ──
3967
+ /** UTC ISO string at the start (midnight) of the given local day. */
3968
+ function dateLocalToUTCStart(dateStr) {
3969
+ if (!dateStr)
3970
+ return dateStr;
3971
+ const [year, month, day] = dateStr.split('-').map(Number);
3972
+ return new Date(year, month - 1, day).toISOString().replace(/\.\d{3}Z$/, 'Z');
3973
+ }
3974
+ /** Start of the day AFTER the given local date (exclusive range end). */
3975
+ function dateLocalToUTCEndExclusive(dateStr) {
3976
+ if (!dateStr)
3977
+ return dateStr;
3978
+ const [year, month, day] = dateStr.split('-').map(Number);
3979
+ return new Date(year, month - 1, day + 1).toISOString().replace(/\.\d{3}Z$/, 'Z');
3980
+ }
3981
+ /** Stored UTC ISO string back to the local "YYYY-MM-DD" date. */
3982
+ function utcISOToLocalDate(utcStr) {
3983
+ if (!utcStr)
3984
+ return utcStr;
3985
+ const d = new Date(utcStr);
3986
+ if (isNaN(d.getTime()))
3987
+ return utcStr;
3988
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
3989
+ }
3990
+ /** The stored "to" is the exclusive end (next midnight); subtract a day to recover the entered date. */
3991
+ function utcISOToLocalDateExclusiveEnd(utcStr) {
3992
+ if (!utcStr)
3993
+ return utcStr;
3994
+ const d = new Date(utcStr);
3995
+ if (isNaN(d.getTime()))
3996
+ return utcStr;
3997
+ d.setDate(d.getDate() - 1);
3998
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
3999
+ }
4000
+ /** Applies the local→UTC conversion when a DATETIME filter is submitted.
4001
+ * Exact date → range covering the full local day. */
4002
+ function normalizeDatetimeFilter(f) {
4003
+ const normalized = Object.assign({}, f);
4004
+ if (f.dataType === 'DATETIME' && f.operator !== 'isEmpty' && f.operator !== 'isNotEmpty') {
4005
+ if (typeof normalized.value === 'string' && normalized.value) {
4006
+ normalized.from = dateLocalToUTCStart(normalized.value);
4007
+ normalized.to = dateLocalToUTCEndExclusive(normalized.value);
4008
+ normalized.value = undefined;
4009
+ }
4010
+ else {
4011
+ if (typeof normalized.from === 'string' && normalized.from)
4012
+ normalized.from = dateLocalToUTCStart(normalized.from);
4013
+ if (typeof normalized.to === 'string' && normalized.to)
4014
+ normalized.to = dateLocalToUTCEndExclusive(normalized.to);
4015
+ }
4016
+ }
4017
+ return normalized;
4018
+ }
4019
+ /** Converts a stored DATETIME filter back to local dates for the popup.
4020
+ * A range covering a single local day is restored to exact-date mode. */
4021
+ function datetimeFilterToDisplay(existing) {
4022
+ const display = Object.assign({}, existing);
4023
+ if (typeof display.from === 'string' && display.from)
4024
+ display.from = utcISOToLocalDate(display.from);
4025
+ if (typeof display.to === 'string' && display.to)
4026
+ display.to = utcISOToLocalDateExclusiveEnd(display.to);
4027
+ if (display.from && display.to && display.from === display.to) {
4028
+ return Object.assign(Object.assign({}, display), { value: display.from, from: undefined, to: undefined });
4029
+ }
4030
+ return display;
4031
+ }
4032
+
4033
+ /**
4034
+ * Stateless render parts of mrd-table. All state and handlers stay in the
4035
+ * component; these components receive plain values and callbacks.
4036
+ */
4037
+ const FilterIcon = () => (index.h("span", { class: "mrd-table__filter-icon", "aria-hidden": "true" }, index.h("svg", { viewBox: "0 0 24 24", width: "14", height: "14", fill: "currentColor" }, index.h("path", { d: "M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z" }))));
4038
+ const TEXTBLOCK_MAX = 200;
4039
+ const TableCell = ({ col, row, locale, onDownload, onOpenTextblock, onOpenJson }) => {
4040
+ var _a, _b, _c;
4041
+ const dataType = (_a = col.dataType) !== null && _a !== void 0 ? _a : '';
4042
+ const isNumeric = col.type === 'FIELD' && NUMERIC_TYPES.has(dataType);
4043
+ const isFile = col.type === 'FIELD' && (dataType === 'FILE' || dataType === 'IMAGE');
4044
+ if (isFile) {
4045
+ const name = (_b = col.name) !== null && _b !== void 0 ? _b : '';
4046
+ const fileVal = row === null || row === void 0 ? void 0 : row[name];
4047
+ const href = fileVal === null || fileVal === void 0 ? void 0 : fileVal.href;
4048
+ const fileName = fileVal === null || fileVal === void 0 ? void 0 : fileVal.fileName;
4049
+ return (index.h("td", { class: "mrd-table__cell" }, href && fileName ? (index.h("button", { class: "mrd-table__file-btn", title: fileName, onClick: (e) => {
4050
+ e.stopPropagation();
4051
+ onDownload({ href, fileName });
4052
+ } }, index.h("svg", { class: "mrd-table__file-icon", viewBox: "0 0 24 24", "aria-hidden": "true" }, index.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', locale))) : ''));
4053
+ }
4054
+ if (dataType === 'JSON') {
4055
+ const name = (_c = col.name) !== null && _c !== void 0 ? _c : '';
4056
+ const rawValue = name ? row === null || row === void 0 ? void 0 : row[name] : undefined;
4057
+ if (rawValue == null || rawValue === '')
4058
+ return index.h("td", { class: "mrd-table__cell" });
4059
+ const compactHtml = CellRenderer.formatJson(rawValue, true);
4060
+ const prettyHtml = CellRenderer.formatJson(rawValue, false);
4061
+ return (index.h("td", { class: "mrd-table__cell" }, index.h("span", { class: "mrd-table__json-preview", innerHTML: compactHtml }), index.h("button", { class: "mrd-table__textblock-btn", onClick: (e) => { e.stopPropagation(); onOpenJson(prettyHtml); }, "aria-label": t('textblock_show_more', locale) }, "\u22EF")));
4062
+ }
4063
+ if (dataType === 'TEXTBLOCK') {
4064
+ const full = CellRenderer.render(col, row, locale);
4065
+ if (full.length <= TEXTBLOCK_MAX) {
4066
+ return index.h("td", { class: "mrd-table__cell" }, full);
4067
+ }
4068
+ const preview = full.slice(0, TEXTBLOCK_MAX) + '…';
4069
+ return (index.h("td", { class: "mrd-table__cell" }, preview, index.h("button", { class: "mrd-table__textblock-btn", onClick: (e) => { e.stopPropagation(); onOpenTextblock(full); }, "aria-label": t('textblock_show_more', locale) }, "\u22EF")));
4070
+ }
4071
+ const value = CellRenderer.render(col, row, locale);
4072
+ return (index.h("td", { class: `mrd-table__cell${isNumeric ? ' mrd-table__cell--numeric' : ''}` }, value));
4073
+ };
4074
+ /** Formats the aggregation total for one column, '' when not applicable. */
4075
+ function formatAggregationValue(col, aggregations, locale) {
4076
+ var _a;
4077
+ if (col.type !== 'FIELD' || !col.aggregate || !aggregations)
4078
+ return '';
4079
+ const fn = col.aggregate.toLowerCase();
4080
+ const aggData = aggregations[fn];
4081
+ const val = typeof aggData === 'object' && aggData !== null
4082
+ ? aggData[(_a = col.name) !== null && _a !== void 0 ? _a : '']
4083
+ : undefined;
4084
+ if (val == null)
4085
+ return '';
4086
+ const dt = col.dataType;
4087
+ if (dt === 'INTEGER')
4088
+ return formatNumber(val, locale, { maximumFractionDigits: 0 });
4089
+ if (dt === 'PERCENTAGE')
4090
+ return formatPercentage(val, locale);
4091
+ if (dt === 'CURRENCY' && col.currencyCode)
4092
+ return formatCurrency(val, col.currencyCode, locale);
4093
+ return formatNumber(val, locale);
4094
+ }
4095
+ const TotalsRow = ({ columns, aggregations, locale }) => {
4096
+ if (!aggregations)
4097
+ return null;
4098
+ if (!columns.some(c => c.type === 'FIELD' && c.aggregate))
4099
+ return null;
4100
+ return (index.h("tfoot", null, index.h("tr", { class: "mrd-table__totals-row" }, columns.map(col => {
4101
+ var _a;
4102
+ const val = formatAggregationValue(col, aggregations, locale);
4103
+ const isNumeric = col.type === 'FIELD' && NUMERIC_TYPES.has((_a = col.dataType) !== null && _a !== void 0 ? _a : '');
4104
+ return (index.h("td", { class: `mrd-table__totals-cell${isNumeric ? ' mrd-table__totals-cell--numeric' : ''}` }, val));
4105
+ }))));
4106
+ };
4107
+ const TextblockModal = ({ text, locale, onClose }) => {
4108
+ if (text === null)
4109
+ return null;
4110
+ return (index.h("div", { class: "mrd-table__modal-backdrop", onClick: onClose, role: "dialog", "aria-modal": "true" }, index.h("div", { class: "mrd-table__modal", onClick: (e) => e.stopPropagation() }, index.h("button", { class: "mrd-table__modal-close", onClick: onClose, "aria-label": t('close', locale) }, "\u2715"), index.h("p", { class: "mrd-table__modal-text" }, text))));
4111
+ };
4112
+ const JsonModal = ({ html, locale, onClose }) => {
4113
+ if (html === null)
4114
+ return null;
4115
+ return (index.h("div", { class: "mrd-table__modal-backdrop", onClick: onClose, role: "dialog", "aria-modal": "true" }, index.h("div", { class: "mrd-table__modal", onClick: (e) => e.stopPropagation() }, index.h("button", { class: "mrd-table__modal-close", onClick: onClose, "aria-label": t('close', locale) }, "\u2715"), index.h("pre", { class: "mrd-table__modal-json", innerHTML: html }))));
4116
+ };
4117
+ const Toolbar = ({ locale, filterMode, filterCount, actions, views, activeViewIdx, viewPopoverOpen, createPickerOpen, createTypes, cb }) => {
4118
+ var _a;
4119
+ const hasActions = actions.length > 0;
4120
+ const hasViewSwitcher = views.length > 1;
4121
+ return (index.h("div", { class: "mrd-table__toolbar" }, index.h("div", { class: "mrd-table__toolbar-left" }, index.h("button", { class: `mrd-table__action mrd-table__action--secondary mrd-table__filter-toggle${filterMode ? ' mrd-table__filter-toggle--active' : ''}`, onClick: cb.onFilterToggle }, index.h("svg", { class: "mrd-table__action-icon", viewBox: "0 0 24 24", "aria-hidden": "true" }, index.h("path", { fill: "currentColor", d: "M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z" })), filterCount > 0 && index.h("span", { class: "mrd-table__filter-badge" }, filterCount), index.h("span", { class: "mrd-table__action-tooltip" }, filterMode ? t('table_filter_hide', locale) : t('table_filter', locale), filterCount > 0 ? ` (${filterCount} ${t('table_filter_active', locale)})` : '')), filterCount > 0 && (index.h("button", { class: "mrd-table__action mrd-table__action--secondary", onClick: cb.onClearAllFilters }, index.h("svg", { class: "mrd-table__action-icon", viewBox: "0 0 24 24", "aria-hidden": "true" }, index.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" })), index.h("span", { class: "mrd-table__action-tooltip" }, t('table_filter_clear_all', locale))))), hasViewSwitcher && (index.h("div", { class: "mrd-table__toolbar-center" }, index.h("div", { class: "mrd-table__view-switcher" }, index.h("button", { class: "mrd-table__view-arrow", "aria-label": "Previous view", onClick: () => cb.onViewSwitch((activeViewIdx - 1 + views.length) % views.length) }, "\u25C0"), index.h("div", { class: "mrd-table__view-title-wrap" }, index.h("button", { class: "mrd-table__view-title", onClick: (e) => cb.onToggleViewPopover(e) }, (_a = views[activeViewIdx]) === null || _a === void 0 ? void 0 : _a.label), viewPopoverOpen && (index.h("div", { class: "mrd-table__view-popover", onClick: (e) => e.stopPropagation() }, views.map((v, i) => (index.h("button", { key: String(i), class: `mrd-table__view-popover-item${i === activeViewIdx ? ' mrd-table__view-popover-item--active' : ''}`, onClick: () => {
4122
+ if (i !== activeViewIdx)
4123
+ cb.onViewSwitch(i);
4124
+ cb.onCloseViewPopover();
4125
+ } }, v.label)))))), index.h("button", { class: "mrd-table__view-arrow", "aria-label": "Next view", onClick: () => cb.onViewSwitch((activeViewIdx + 1) % views.length) }, "\u25B6")))), hasActions && (index.h("div", { class: "mrd-table__toolbar-right" }, actions.map(a => {
4126
+ var _a, _b;
4127
+ const pickerTypes = a.action === 'create' ? createTypes : null;
4128
+ if (pickerTypes === null || pickerTypes === void 0 ? void 0 : pickerTypes.length) {
4129
+ return (index.h("div", { class: "mrd-table__create-picker-wrap", key: `action-${a.action}` }, index.h("button", { class: `mrd-table__action mrd-table__action--${(_a = a.variant) !== null && _a !== void 0 ? _a : 'secondary'}`, onClick: cb.onToggleCreatePicker }, a.icon
4130
+ ? index.h("svg", { class: "mrd-table__action-icon", "aria-hidden": "true" }, index.h("use", { href: a.icon }))
4131
+ : a.label, index.h("span", { class: "mrd-table__action-tooltip" }, a.label)), createPickerOpen && (index.h("div", { class: "mrd-table__create-picker" }, pickerTypes.map(ct => (index.h("button", { key: ct.type, class: "mrd-table__create-picker-item", onClick: () => cb.onCreate(ct.type) }, ct.label)))))));
4132
+ }
4133
+ return (index.h("button", { key: `action-${a.action}`, class: `mrd-table__action mrd-table__action--${(_b = a.variant) !== null && _b !== void 0 ? _b : 'secondary'}`, disabled: a.disabled, onClick: () => cb.onAction(a.action) }, a.icon
4134
+ ? index.h("svg", { class: "mrd-table__action-icon", "aria-hidden": "true" }, index.h("use", { href: a.icon }))
4135
+ : a.label, index.h("span", { class: "mrd-table__action-tooltip" }, a.label)));
4136
+ })))));
4137
+ };
4138
+
4139
+ const FilterEditor = ({ col, dataType, openFilterCol, pendingFilter, locale, cb }) => {
4140
+ var _a, _b, _c, _d, _e, _f;
4141
+ const pf = pendingFilter;
4142
+ if (NO_FILTER_TYPES.has(dataType)) {
4143
+ return index.h("p", { class: "mrd-table__filter-no-support" }, t('filter_no_support', locale));
4144
+ }
4145
+ if (dataType === 'BOOLEAN') {
4146
+ const boolOp = pf.operator;
4147
+ const noValueOp = boolOp === 'isEmpty' || boolOp === 'isNotEmpty';
4148
+ return (index.h("div", { class: "mrd-table__filter-radio-group" }, [
4149
+ { labelKey: 'filter_all', value: null },
4150
+ { labelKey: 'yes', value: true },
4151
+ { labelKey: 'no', value: false },
4152
+ ].map(opt => (index.h("label", { class: "mrd-table__filter-radio-label" }, index.h("input", { type: "radio", name: `bf-${openFilterCol}`, checked: !noValueOp && pf.value === opt.value, onChange: () => cb.onReplacePending(Object.assign(Object.assign({}, pf), { operator: undefined, value: opt.value })) }), t(opt.labelKey, locale)))), index.h("label", { class: "mrd-table__filter-radio-label" }, index.h("input", { type: "radio", name: `bf-${openFilterCol}`, checked: boolOp === 'isEmpty', onChange: () => cb.onReplacePending(Object.assign(Object.assign({}, pf), { operator: 'isEmpty', value: undefined })) }), t('filter_is_empty', locale)), index.h("label", { class: "mrd-table__filter-radio-label" }, index.h("input", { type: "radio", name: `bf-${openFilterCol}`, checked: boolOp === 'isNotEmpty', onChange: () => cb.onReplacePending(Object.assign(Object.assign({}, pf), { operator: 'isNotEmpty', value: undefined })) }), t('filter_is_not_empty', locale))));
4153
+ }
4154
+ if (dataType === 'LIST') {
4155
+ const items = (_a = col.listItems) !== null && _a !== void 0 ? _a : [];
4156
+ const selected = (_b = pf.values) !== null && _b !== void 0 ? _b : [];
4157
+ return (index.h("div", { class: "mrd-table__filter-list" }, index.h("div", { class: "mrd-table__filter-list-controls" }, index.h("button", { class: "mrd-table__filter-list-btn", onClick: () => cb.onReplacePending(Object.assign(Object.assign({}, pf), { values: items.map(i => i.key) })) }, t('filter_select_all', locale)), index.h("button", { class: "mrd-table__filter-list-btn", onClick: () => cb.onReplacePending(Object.assign(Object.assign({}, pf), { values: [] })) }, t('filter_select_none', locale))), items.map(item => (index.h("label", { class: "mrd-table__filter-checkbox-label" }, index.h("input", { type: "checkbox", checked: selected.includes(item.key), onChange: (e) => cb.onToggleValue(item.key, e.target.checked) }), item.label)))));
4158
+ }
4159
+ if (TEXT_TYPES.has(dataType) || dataType === 'RELATION') {
4160
+ const op = (_c = pf.operator) !== null && _c !== void 0 ? _c : 'startsWith';
4161
+ const noInput = op === 'isEmpty' || op === 'isNotEmpty';
4162
+ return (index.h("div", { class: "mrd-table__filter-editor" }, index.h("select", { class: "mrd-table__filter-select", onChange: (e) => cb.onSetPending('operator', e.target.value) }, [
4163
+ { val: 'startsWith', labelKey: 'filter_starts_with' },
4164
+ { val: 'equals', labelKey: 'filter_equals' },
4165
+ { val: 'isEmpty', labelKey: 'filter_is_empty' },
4166
+ { val: 'isNotEmpty', labelKey: 'filter_is_not_empty' },
4167
+ ].map(o => index.h("option", { value: o.val, selected: op === o.val }, t(o.labelKey, locale)))), !noInput && (index.h("input", { type: "text", class: "mrd-table__filter-input", value: String((_d = pf.value) !== null && _d !== void 0 ? _d : ''), placeholder: t('filter_search_value', locale), onInput: (e) => cb.onSetPending('value', e.target.value) }))));
4168
+ }
4169
+ if (NUMERIC_TYPES.has(dataType)) {
4170
+ const numOp = pf.operator;
4171
+ const noInput = numOp === 'isEmpty' || numOp === 'isNotEmpty';
4172
+ const rangeMode = !noInput && (pf.from !== undefined || pf.to !== undefined);
4173
+ return (index.h("div", { class: "mrd-table__filter-editor" }, index.h("select", { class: "mrd-table__filter-select", onChange: (e) => {
4174
+ const val = e.target.value;
4175
+ if (val === 'isEmpty' || val === 'isNotEmpty') {
4176
+ cb.onReplacePending(Object.assign(Object.assign({}, pf), { operator: val, value: undefined, from: undefined, to: undefined }));
4177
+ }
4178
+ else {
4179
+ cb.onReplacePending(Object.assign(Object.assign({}, pf), { operator: undefined }));
4180
+ }
4181
+ } }, index.h("option", { value: "", selected: !noInput }, t('filter_has_value', locale)), index.h("option", { value: "isEmpty", selected: numOp === 'isEmpty' }, t('filter_is_empty', locale)), index.h("option", { value: "isNotEmpty", selected: numOp === 'isNotEmpty' }, t('filter_is_not_empty', locale))), !noInput && (index.h("div", { class: "mrd-table__filter-editor" }, index.h("div", { class: "mrd-table__filter-radio-group mrd-table__filter-radio-group--inline" }, index.h("label", { class: "mrd-table__filter-radio-label" }, index.h("input", { type: "radio", name: `nm-${openFilterCol}`, checked: !rangeMode, onChange: () => cb.onReplacePending(Object.assign(Object.assign({}, pf), { from: undefined, to: undefined })) }), t('filter_exact', locale)), index.h("label", { class: "mrd-table__filter-radio-label" }, index.h("input", { type: "radio", name: `nm-${openFilterCol}`, checked: rangeMode, onChange: () => cb.onReplacePending(Object.assign(Object.assign({}, pf), { value: undefined, from: null, to: null })) }), t('filter_range', locale))), !rangeMode ? (index.h("input", { type: "number", class: "mrd-table__filter-input", value: pf.value != null ? String(pf.value) : '', onInput: (e) => cb.onSetPending('value', e.target.value) })) : (index.h("div", { class: "mrd-table__filter-range" }, index.h("input", { type: "number", class: "mrd-table__filter-input", placeholder: t('filter_from', locale), value: pf.from != null ? String(pf.from) : '', onInput: (e) => cb.onSetPending('from', e.target.value) }), index.h("span", { class: "mrd-table__filter-range-sep" }, "\u2013"), index.h("input", { type: "number", class: "mrd-table__filter-input", placeholder: t('filter_to', locale), value: pf.to != null ? String(pf.to) : '', onInput: (e) => cb.onSetPending('to', e.target.value) })))))));
4182
+ }
4183
+ if (dataType === 'DATETIME') {
4184
+ const dtOp = pf.operator;
4185
+ const noInput = dtOp === 'isEmpty' || dtOp === 'isNotEmpty';
4186
+ const rangeMode = !noInput && (pf.from !== undefined || pf.to !== undefined);
4187
+ return (index.h("div", { class: "mrd-table__filter-editor" }, index.h("select", { class: "mrd-table__filter-select", onChange: (e) => {
4188
+ const val = e.target.value;
4189
+ if (val === 'isEmpty' || val === 'isNotEmpty') {
4190
+ cb.onReplacePending(Object.assign(Object.assign({}, pf), { operator: val, value: undefined, from: undefined, to: undefined }));
4191
+ }
4192
+ else {
4193
+ cb.onReplacePending(Object.assign(Object.assign({}, pf), { operator: undefined }));
4194
+ }
4195
+ } }, index.h("option", { value: "", selected: !noInput }, t('filter_has_value', locale)), index.h("option", { value: "isEmpty", selected: dtOp === 'isEmpty' }, t('filter_is_empty', locale)), index.h("option", { value: "isNotEmpty", selected: dtOp === 'isNotEmpty' }, t('filter_is_not_empty', locale))), !noInput && (index.h("div", { class: "mrd-table__filter-editor" }, index.h("div", { class: "mrd-table__filter-radio-group mrd-table__filter-radio-group--inline" }, index.h("label", { class: "mrd-table__filter-radio-label" }, index.h("input", { type: "radio", name: `dt-${openFilterCol}`, checked: !rangeMode, onChange: () => cb.onReplacePending(Object.assign(Object.assign({}, pf), { from: undefined, to: undefined })) }), t('filter_exact', locale)), index.h("label", { class: "mrd-table__filter-radio-label" }, index.h("input", { type: "radio", name: `dt-${openFilterCol}`, checked: rangeMode, onChange: () => cb.onReplacePending(Object.assign(Object.assign({}, pf), { value: undefined, from: null, to: null })) }), t('filter_range', locale))), !rangeMode ? (index.h("input", { type: "date", class: "mrd-table__filter-input", value: String((_e = pf.value) !== null && _e !== void 0 ? _e : ''), onInput: (e) => cb.onSetPending('value', e.target.value) })) : (index.h("div", { class: "mrd-table__filter-range mrd-table__filter-range--stacked" }, index.h("label", { class: "mrd-table__filter-range-label" }, t('filter_from', locale)), index.h("input", { type: "date", class: "mrd-table__filter-input", value: pf.from != null ? String(pf.from) : '', onInput: (e) => cb.onSetPending('from', e.target.value) }), index.h("label", { class: "mrd-table__filter-range-label" }, t('filter_to', locale)), index.h("input", { type: "date", class: "mrd-table__filter-input", value: pf.to != null ? String(pf.to) : '', onInput: (e) => cb.onSetPending('to', e.target.value) })))))));
4196
+ }
4197
+ if (DATE_TYPES.has(dataType)) {
4198
+ const inputType = dataType === 'DATE' ? 'date' : 'time';
4199
+ const dtdOp = pf.operator;
4200
+ const noInput = dtdOp === 'isEmpty' || dtdOp === 'isNotEmpty';
4201
+ const rangeMode = !noInput && (pf.from !== undefined || pf.to !== undefined);
4202
+ return (index.h("div", { class: "mrd-table__filter-editor" }, index.h("select", { class: "mrd-table__filter-select", onChange: (e) => {
4203
+ const val = e.target.value;
4204
+ if (val === 'isEmpty' || val === 'isNotEmpty') {
4205
+ cb.onReplacePending(Object.assign(Object.assign({}, pf), { operator: val, value: undefined, from: undefined, to: undefined }));
4206
+ }
4207
+ else {
4208
+ cb.onReplacePending(Object.assign(Object.assign({}, pf), { operator: undefined }));
4209
+ }
4210
+ } }, index.h("option", { value: "", selected: !noInput }, t('filter_has_value', locale)), index.h("option", { value: "isEmpty", selected: dtdOp === 'isEmpty' }, t('filter_is_empty', locale)), index.h("option", { value: "isNotEmpty", selected: dtdOp === 'isNotEmpty' }, t('filter_is_not_empty', locale))), !noInput && (index.h("div", { class: "mrd-table__filter-editor" }, index.h("div", { class: "mrd-table__filter-radio-group mrd-table__filter-radio-group--inline" }, index.h("label", { class: "mrd-table__filter-radio-label" }, index.h("input", { type: "radio", name: `dt-${openFilterCol}`, checked: !rangeMode, onChange: () => cb.onReplacePending(Object.assign(Object.assign({}, pf), { from: undefined, to: undefined })) }), t('filter_exact', locale)), index.h("label", { class: "mrd-table__filter-radio-label" }, index.h("input", { type: "radio", name: `dt-${openFilterCol}`, checked: rangeMode, onChange: () => cb.onReplacePending(Object.assign(Object.assign({}, pf), { value: undefined, from: null, to: null })) }), t('filter_range', locale))), !rangeMode ? (index.h("input", { type: inputType, class: "mrd-table__filter-input", value: String((_f = pf.value) !== null && _f !== void 0 ? _f : ''), onInput: (e) => cb.onSetPending('value', e.target.value) })) : (index.h("div", { class: "mrd-table__filter-range" }, index.h("input", { type: inputType, class: "mrd-table__filter-input", placeholder: t('filter_from', locale), value: pf.from != null ? String(pf.from) : '', onInput: (e) => cb.onSetPending('from', e.target.value) }), index.h("input", { type: inputType, class: "mrd-table__filter-input", placeholder: t('filter_to', locale), value: pf.to != null ? String(pf.to) : '', onInput: (e) => cb.onSetPending('to', e.target.value) })))))));
4211
+ }
4212
+ return null;
4213
+ };
4214
+ const FilterPopup = (props) => {
4215
+ var _a;
4216
+ const { col, openFilterCol, popupPos, sortField, sortDir, locale, cb } = props;
4217
+ const label = (_a = col.label) !== null && _a !== void 0 ? _a : openFilterCol;
4218
+ const sortActive = sortField === openFilterCol;
4219
+ return (index.h("div", { class: "mrd-table__filter-popup", style: { top: `${popupPos.top}px`, left: `${popupPos.left}px` }, onClick: (e) => e.stopPropagation() }, index.h("div", { class: "mrd-table__filter-popup-header" }, index.h("span", { class: "mrd-table__filter-popup-title" }, label), index.h("button", { class: "mrd-table__filter-close", onClick: cb.onClose }, "\u2715")), index.h("div", { class: "mrd-table__filter-section" }, index.h("div", { class: "mrd-table__filter-section-label" }, t('filter_sorting', locale)), index.h("div", { class: "mrd-table__filter-sort-buttons" }, index.h("button", { class: `mrd-table__filter-sort-btn${sortActive && sortDir === 'asc' ? ' mrd-table__filter-sort-btn--active' : ''}`, onClick: () => cb.onApplySort('asc') }, "\u25B2 ", t('filter_ascending', locale)), index.h("button", { class: `mrd-table__filter-sort-btn${sortActive && sortDir === 'desc' ? ' mrd-table__filter-sort-btn--active' : ''}`, onClick: () => cb.onApplySort('desc') }, "\u25BC ", t('filter_descending', locale)))), index.h("div", { class: "mrd-table__filter-divider" }), index.h("div", { class: "mrd-table__filter-section" }, index.h("div", { class: "mrd-table__filter-section-label" }, t('filter_section', locale)), index.h(FilterEditor, Object.assign({}, props))), index.h("div", { class: "mrd-table__filter-popup-footer" }, index.h("button", { class: "mrd-table__filter-btn mrd-table__filter-btn--clear", onClick: cb.onClear }, t('filter_clear', locale)), index.h("button", { class: "mrd-table__filter-btn mrd-table__filter-btn--apply", onClick: cb.onApply }, t('filter_apply', locale)))));
4220
+ };
4221
+
4222
+ /**
4223
+ * Pure window/paging maths for the mrd-table virtual scroll.
4224
+ * The window state itself stays @State in the component; these
4225
+ * functions only compute values from it.
4226
+ */
4227
+ const BUFFER = 10;
4228
+ /** Wait this long (ms) after the last scroll event before requesting pages,
4229
+ * so pages the user quickly scrolls past are skipped. */
4230
+ const REQUEST_DEBOUNCE_MS = 150;
4231
+ function visibleCount(tableHeight, rowHeight) {
4232
+ return Math.ceil(tableHeight / rowHeight);
4233
+ }
4234
+ /** Render window (with buffer) for the given scroll offset. */
4235
+ function computeWindow(scrollTop, rowHeight, tableHeight, total) {
4236
+ const visStart = Math.floor(scrollTop / rowHeight);
4237
+ const visEnd = Math.min(visStart + visibleCount(tableHeight, rowHeight), total - 1);
4238
+ return {
4239
+ renderStart: Math.max(0, visStart - BUFFER),
4240
+ renderEnd: Math.min(total - 1, visEnd + BUFFER),
4241
+ };
4242
+ }
4243
+ /** First/last page (0-based) covering the given row window. */
4244
+ function pageRange(start, end, pageSize) {
4245
+ return { firstPage: Math.floor(start / pageSize), lastPage: Math.floor(end / pageSize) };
4246
+ }
4247
+ function getRowFromPages(pages, index, pageSize) {
4248
+ var _a;
4249
+ const page = pages.get(Math.floor(index / pageSize));
4250
+ return (_a = page === null || page === void 0 ? void 0 : page[index % pageSize]) !== null && _a !== void 0 ? _a : null;
4251
+ }
4252
+ /** Authoritative row count: a page shorter than pageSize is the last page,
4253
+ * so the true total cannot exceed its end index. */
4254
+ function computeEffectiveTotal(loadedPages, pageSize, baseTotal) {
4255
+ let effectiveTotal = baseTotal;
4256
+ for (const [pageNum, pageRows] of loadedPages) {
4257
+ if (pageRows.length < pageSize) {
4258
+ effectiveTotal = Math.min(effectiveTotal, pageNum * pageSize + pageRows.length);
4259
+ }
4260
+ }
4261
+ return effectiveTotal;
4262
+ }
4263
+ /** True when some loaded page was short — the exact total is then known. */
4264
+ function isTotalKnownFromPages(loadedPages, pageSize) {
4265
+ for (const rows of loadedPages.values()) {
4266
+ if (rows.length < pageSize)
4267
+ return true;
4268
+ }
4269
+ return false;
4270
+ }
4271
+
4272
+ const mrdTableCss = () => `@charset "UTF-8";.sc-mrd-table-h{display:block;width:100%}.mrd-table__scroll.sc-mrd-table{overflow-y:auto;overflow-x:auto;border:1px solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);overflow-anchor:none}.mrd-table.sc-mrd-table{overflow-x:auto}.mrd-table__table.sc-mrd-table{width:auto;min-width:100%;border-collapse:collapse;font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-900)}.mrd-table__scroll.sc-mrd-table .mrd-table__table.sc-mrd-table{min-width:max-content}.mrd-table__header.sc-mrd-table{position:sticky;top:0;z-index:1;background:var(--mrd-color-white);text-align:left;padding:var(--mrd-space-2) var(--mrd-space-4);border-bottom:2px solid var(--mrd-border-color);color:var(--mrd-color-neutral-600);font-weight:var(--mrd-font-weight-medium);white-space:nowrap;font-size:var(--mrd-font-size-xs);text-transform:uppercase;letter-spacing:0.04em}.mrd-table__header--sortable.sc-mrd-table{cursor:pointer;user-select:none}.mrd-table__header--sortable.sc-mrd-table:hover{background:var(--mrd-color-neutral-50);color:var(--mrd-color-neutral-800)}.mrd-table__header--sorted-asc.sc-mrd-table,.mrd-table__header--sorted-desc.sc-mrd-table{color:var(--mrd-color-primary);border-bottom-color:var(--mrd-color-primary)}.mrd-table__header-label.sc-mrd-table{margin-right:var(--mrd-space-1)}.mrd-table__sort-icon.sc-mrd-table{font-size:0.85rem;opacity:0.4;vertical-align:middle}.mrd-table__header--sorted-asc.sc-mrd-table .mrd-table__sort-icon.sc-mrd-table,.mrd-table__header--sorted-desc.sc-mrd-table .mrd-table__sort-icon.sc-mrd-table{opacity:1;color:var(--mrd-color-primary)}.mrd-table__filter-icon.sc-mrd-table{display:inline-flex;align-items:center;vertical-align:middle;margin-left:var(--mrd-space-1);color:var(--mrd-color-primary)}.mrd-table__row.sc-mrd-table{border-bottom:1px solid var(--mrd-border-color)}.mrd-table__row.sc-mrd-table:hover{background:var(--mrd-color-neutral-200) !important}.mrd-table__row--clickable.sc-mrd-table{cursor:pointer}.mrd-table__spacer.sc-mrd-table{border:none}.mrd-table__spacer.sc-mrd-table td.sc-mrd-table{padding:0;border:none}.mrd-table__cell.sc-mrd-table{padding:var(--mrd-space-2) var(--mrd-space-4);vertical-align:top;white-space:nowrap}.mrd-table__cell--numeric.sc-mrd-table{text-align:right;font-variant-numeric:tabular-nums}.mrd-table__row--loading.sc-mrd-table{background:transparent}.mrd-table__cell--placeholder.sc-mrd-table{padding:var(--mrd-space-2) var(--mrd-space-4);border-bottom:1px solid var(--mrd-border-color)}.mrd-table__placeholder-bar.sc-mrd-table{display:block;height:0.75rem;width:55%;border-radius:var(--mrd-border-radius-sm);background:linear-gradient(90deg, var(--mrd-color-neutral-200) 25%, var(--mrd-color-neutral-100) 50%, var(--mrd-color-neutral-200) 75%);background-size:200% 100%;animation:mrd-shimmer 1.4s ease infinite}@keyframes mrd-shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}.mrd-table__toolbar.sc-mrd-table{display:flex;align-items:center;justify-content:space-between;padding-bottom:var(--mrd-space-2)}.mrd-table__toolbar-left.sc-mrd-table,.mrd-table__toolbar-right.sc-mrd-table{display:flex;gap:var(--mrd-space-2);align-items:center}.mrd-table__toolbar-center.sc-mrd-table{flex:1;display:flex;justify-content:center;align-items:center;gap:var(--mrd-space-1)}.mrd-table__view-switcher.sc-mrd-table{display:flex;align-items:center;gap:var(--mrd-space-1)}.mrd-table__view-arrow.sc-mrd-table{background:none;border:none;cursor:pointer;padding:0 var(--mrd-space-1);color:var(--mrd-color-neutral-500);font-size:var(--mrd-font-size-xs);line-height:1}.mrd-table__view-arrow.sc-mrd-table:hover{color:var(--mrd-color-neutral-800)}.mrd-table__view-title-wrap.sc-mrd-table{position:relative}.mrd-table__view-title.sc-mrd-table{font-size:var(--mrd-font-size-sm);font-weight:600;color:var(--mrd-color-neutral-800);font-family:var(--mrd-font-family);background:none;border:none;outline:none;cursor:pointer;padding:0 var(--mrd-space-1);max-width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mrd-table__view-title.sc-mrd-table:hover{color:var(--mrd-color-primary)}.mrd-table__view-popover.sc-mrd-table{position:absolute;top:calc(100% + var(--mrd-space-1));left:50%;transform:translateX(-50%);background:var(--mrd-color-white);border:1px solid var(--mrd-color-neutral-200);border-radius:var(--mrd-radius-md);box-shadow:var(--mrd-shadow-md);z-index:100;min-width:160px;padding:var(--mrd-space-1) 0}.mrd-table__view-popover-item.sc-mrd-table{display:block;width:100%;text-align:left;background:none;border:none;cursor:pointer;padding:var(--mrd-space-2) var(--mrd-space-3);font-size:var(--mrd-font-size-sm);font-family:var(--mrd-font-family);color:var(--mrd-color-neutral-700);white-space:nowrap}.mrd-table__view-popover-item.sc-mrd-table:hover{background:var(--mrd-color-neutral-50)}.mrd-table__view-popover-item--active.sc-mrd-table{font-weight:600;color:var(--mrd-color-primary)}.mrd-table__action.sc-mrd-table{position:relative;display:inline-flex;align-items:center;justify-content:center;width:2rem;height:2rem;padding:0;background:transparent;border:1px solid transparent;border-radius:var(--mrd-border-radius);cursor:pointer;color:var(--mrd-color-neutral-400);transition:background-color 0.15s, border-color 0.15s, color 0.15s}.mrd-table__action.sc-mrd-table:hover{background-color:var(--mrd-color-neutral-100);border-color:var(--mrd-color-neutral-300);color:var(--mrd-color-neutral-700)}.mrd-table__action.sc-mrd-table:disabled{opacity:0.4;cursor:not-allowed}.mrd-table__action--primary.sc-mrd-table{color:var(--mrd-color-neutral-500)}.mrd-table__action--primary.sc-mrd-table:hover{background:var(--mrd-color-primary);border-color:var(--mrd-color-primary);color:var(--mrd-color-white)}.mrd-table__action--danger.sc-mrd-table{color:var(--mrd-color-error)}.mrd-table__action--danger.sc-mrd-table:hover{background-color:var(--mrd-color-error-light, #fef2f2);border-color:var(--mrd-color-error)}.mrd-table__action-icon.sc-mrd-table{width:1.25rem;height:1.25rem;pointer-events:none;fill:currentColor}.mrd-table__action-tooltip.sc-mrd-table{display:none;position:absolute;bottom:calc(100% + 6px);right:0;padding:var(--mrd-space-1) var(--mrd-space-2);font-size:var(--mrd-font-size-xs);white-space:nowrap;background:var(--mrd-color-tooltip, #fffce1);color:var(--mrd-color-neutral-900);border:1px solid var(--mrd-border-color);border-radius:var(--mrd-border-radius-sm, var(--mrd-border-radius));pointer-events:none;z-index:10}.mrd-table__action.sc-mrd-table:hover .mrd-table__action-tooltip.sc-mrd-table{display:block}.mrd-table__create-picker-wrap.sc-mrd-table{position:relative}.mrd-table__create-picker.sc-mrd-table{position:absolute;right:0;top:calc(100% + 4px);background:var(--mrd-color-white, #fff);border:1px solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);box-shadow:var(--mrd-shadow-md, 0 4px 12px rgba(0, 0, 0, 0.12));z-index:10;min-width:10rem;padding:var(--mrd-space-1) 0}.mrd-table__create-picker-item.sc-mrd-table{display:block;width:100%;text-align:left;padding:var(--mrd-space-2) var(--mrd-space-3);background:none;border:none;cursor:pointer;font-size:var(--mrd-font-size-sm);font-family:var(--mrd-font-family);color:var(--mrd-color-neutral-800)}.mrd-table__create-picker-item.sc-mrd-table:hover{background:var(--mrd-color-neutral-50);color:var(--mrd-color-neutral-900)}.mrd-table__filter-toggle--active.sc-mrd-table{background:var(--mrd-color-primary);border-color:var(--mrd-color-primary);color:var(--mrd-color-white)}.mrd-table__filter-toggle--active.sc-mrd-table:hover{background:var(--mrd-color-primary-dark, var(--mrd-color-primary));border-color:var(--mrd-color-primary-dark, var(--mrd-color-primary));color:var(--mrd-color-white)}.mrd-table__filter-badge.sc-mrd-table{position:absolute;top:-6px;right:-6px;min-width:1.25rem;height:1.25rem;padding:0 3px;background:var(--mrd-color-error, #e53e3e);color:var(--mrd-color-white);border-radius:9999px;font-size:0.65rem;font-weight:var(--mrd-font-weight-medium);line-height:1.25rem;text-align:center;pointer-events:none}.mrd-table__header--filtered.sc-mrd-table{color:var(--mrd-color-primary);border-bottom-color:var(--mrd-color-primary)}.mrd-table__filter-popup.sc-mrd-table{position:fixed;width:280px;background:var(--mrd-color-white);border:1px solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);box-shadow:var(--mrd-shadow-md, 0 4px 12px rgba(0, 0, 0, 0.12));z-index:var(--mrd-z-dropdown, 200);font-size:var(--mrd-font-size-sm)}.mrd-table__filter-popup-header.sc-mrd-table{display:flex;align-items:center;justify-content:space-between;padding:var(--mrd-space-2) var(--mrd-space-3);border-bottom:1px solid var(--mrd-border-color)}.mrd-table__filter-popup-title.sc-mrd-table{font-weight:var(--mrd-font-weight-medium);color:var(--mrd-color-neutral-800);font-size:var(--mrd-font-size-sm)}.mrd-table__filter-close.sc-mrd-table{background:transparent;border:none;cursor:pointer;color:var(--mrd-color-neutral-500);font-size:0.9rem;padding:2px 4px;border-radius:3px;line-height:1}.mrd-table__filter-close.sc-mrd-table:hover{background:var(--mrd-color-neutral-100);color:var(--mrd-color-neutral-800)}.mrd-table__filter-section.sc-mrd-table{padding:var(--mrd-space-2) var(--mrd-space-3)}.mrd-table__filter-section-label.sc-mrd-table{font-size:var(--mrd-font-size-xs);font-weight:var(--mrd-font-weight-medium);text-transform:uppercase;letter-spacing:0.04em;color:var(--mrd-color-neutral-500);margin-bottom:var(--mrd-space-2)}.mrd-table__filter-sort-buttons.sc-mrd-table{display:flex;gap:var(--mrd-space-2)}.mrd-table__filter-sort-btn.sc-mrd-table{flex:1;padding:var(--mrd-space-1) var(--mrd-space-2);background:transparent;border:1px solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);cursor:pointer;font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-700)}.mrd-table__filter-sort-btn.sc-mrd-table:hover{background:var(--mrd-color-neutral-100)}.mrd-table__filter-sort-btn--active.sc-mrd-table{background:var(--mrd-color-primary);border-color:var(--mrd-color-primary);color:var(--mrd-color-white)}.mrd-table__filter-divider.sc-mrd-table{height:1px;background:var(--mrd-border-color);margin:0}.mrd-table__filter-editor.sc-mrd-table{display:flex;flex-direction:column;gap:var(--mrd-space-2)}.mrd-table__filter-select.sc-mrd-table,.mrd-table__filter-input.sc-mrd-table{width:100%;padding:var(--mrd-space-1) var(--mrd-space-2);border:1px solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-900);background:var(--mrd-color-white);box-sizing:border-box}.mrd-table__filter-select.sc-mrd-table:focus,.mrd-table__filter-input.sc-mrd-table:focus{outline:none;border-color:var(--mrd-color-primary);box-shadow:0 0 0 2px rgba(0, 0, 0, 0.06)}.mrd-table__filter-range.sc-mrd-table{display:flex;align-items:center;gap:var(--mrd-space-1)}.mrd-table__filter-range.sc-mrd-table .mrd-table__filter-input.sc-mrd-table{flex:1;min-width:0}.mrd-table__filter-range-sep.sc-mrd-table{color:var(--mrd-color-neutral-400);flex-shrink:0}.mrd-table__filter-range--stacked.sc-mrd-table{flex-direction:column;align-items:stretch;gap:var(--mrd-space-2)}.mrd-table__filter-range-label.sc-mrd-table{font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-500);margin-bottom:2px}.mrd-table__filter-radio-group.sc-mrd-table{display:flex;flex-direction:column;gap:var(--mrd-space-1)}.mrd-table__filter-radio-group--inline.sc-mrd-table{flex-direction:row;gap:var(--mrd-space-3)}.mrd-table__filter-radio-label.sc-mrd-table{display:flex;align-items:center;gap:var(--mrd-space-1);cursor:pointer;font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-800)}.mrd-table__filter-list.sc-mrd-table{display:flex;flex-direction:column;gap:var(--mrd-space-1);max-height:180px;overflow-y:auto}.mrd-table__filter-list-controls.sc-mrd-table{display:flex;gap:var(--mrd-space-2);margin-bottom:var(--mrd-space-1)}.mrd-table__filter-list-btn.sc-mrd-table{font-size:var(--mrd-font-size-xs);color:var(--mrd-color-primary);background:transparent;border:none;cursor:pointer;padding:0;text-decoration:underline}.mrd-table__filter-checkbox-label.sc-mrd-table{display:flex;align-items:center;gap:var(--mrd-space-1);cursor:pointer;font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-800)}.mrd-table__filter-no-support.sc-mrd-table{font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-500);margin:0;font-style:italic}.mrd-table__filter-popup-footer.sc-mrd-table{display:flex;justify-content:flex-end;gap:var(--mrd-space-2);padding:var(--mrd-space-2) var(--mrd-space-3);border-top:1px solid var(--mrd-border-color)}.mrd-table__filter-btn.sc-mrd-table{padding:var(--mrd-space-1) var(--mrd-space-3);border-radius:var(--mrd-border-radius);border:1px solid var(--mrd-border-color);font-size:var(--mrd-font-size-sm);cursor:pointer}.mrd-table__filter-btn--clear.sc-mrd-table{background:transparent;color:var(--mrd-color-neutral-600)}.mrd-table__filter-btn--clear.sc-mrd-table:hover{background:var(--mrd-color-neutral-100)}.mrd-table__filter-btn--apply.sc-mrd-table{background:var(--mrd-color-primary);border-color:var(--mrd-color-primary);color:var(--mrd-color-white)}.mrd-table__filter-btn--apply.sc-mrd-table:hover{background:var(--mrd-color-primary-dark, var(--mrd-color-primary));border-color:var(--mrd-color-primary-dark, var(--mrd-color-primary))}.mrd-table__totals-row.sc-mrd-table{border-top:2px solid var(--mrd-border-color)}.mrd-table__totals-cell.sc-mrd-table{position:sticky;bottom:0;z-index:2;padding:var(--mrd-space-2) var(--mrd-space-4);background:var(--mrd-color-white);font-weight:var(--mrd-font-weight-medium);font-variant-numeric:tabular-nums;white-space:nowrap;border-top:2px solid var(--mrd-border-color)}.mrd-table__totals-cell--numeric.sc-mrd-table{text-align:right}.mrd-table__footer.sc-mrd-table{padding:var(--mrd-space-1) var(--mrd-space-2);font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-500);text-align:right}.mrd-table__empty.sc-mrd-table{padding:var(--mrd-space-4) var(--mrd-space-3);color:var(--mrd-color-neutral-500);font-size:var(--mrd-font-size-sm);text-align:center;margin:0}.mrd-table__file-btn.sc-mrd-table{display:inline-flex;align-items:center;gap:var(--mrd-space-1);background:none;border:none;padding:0;cursor:pointer;color:var(--mrd-color-primary);font-size:var(--mrd-font-size-sm);font-family:inherit;max-width:100%;overflow:hidden}.mrd-table__file-btn.sc-mrd-table:hover{text-decoration:underline;color:var(--mrd-color-primary-dark)}.mrd-table__file-icon.sc-mrd-table{flex-shrink:0;width:1rem;height:1rem}.mrd-table__textblock-btn.sc-mrd-table{display:inline;background:none;border:none;padding:0 0 0 var(--mrd-space-1);cursor:pointer;color:var(--mrd-color-primary);font-size:var(--mrd-font-size-sm);font-family:inherit;line-height:inherit;vertical-align:middle}.mrd-table__textblock-btn.sc-mrd-table:hover{color:var(--mrd-color-primary-dark)}.mrd-table__modal-backdrop.sc-mrd-table{position:fixed;inset:0;background:rgba(0, 0, 0, 0.4);z-index:var(--mrd-z-modal, 300);display:flex;align-items:center;justify-content:center}.mrd-table__modal.sc-mrd-table{background:#fff;border-radius:var(--mrd-radius-md, 0.5rem);padding:var(--mrd-space-6);max-width:min(600px, 90vw);max-height:70vh;overflow-y:auto;position:relative;box-shadow:var(--mrd-shadow-lg)}.mrd-table__modal-close.sc-mrd-table{position:absolute;top:var(--mrd-space-3);right:var(--mrd-space-3);background:none;border:none;cursor:pointer;font-size:1.25rem;line-height:1;color:var(--mrd-color-text-muted, #6b7280);padding:0}.mrd-table__modal-close.sc-mrd-table:hover{color:var(--mrd-color-text, #111827)}.mrd-table__modal-text.sc-mrd-table{margin:0;padding-right:var(--mrd-space-6);white-space:pre-wrap;word-break:break-word;font-size:var(--mrd-font-size-sm);line-height:1.6}.mrd-table__json-preview.sc-mrd-table{font-family:var(--mrd-font-family-mono);font-size:var(--mrd-font-size-xs);overflow:hidden;white-space:nowrap;text-overflow:ellipsis;display:inline-block;max-width:calc(100% - 1.5rem);vertical-align:middle}.mrd-table__modal-json.sc-mrd-table{margin:0;padding-right:var(--mrd-space-6);font-family:var(--mrd-font-family-mono);font-size:var(--mrd-font-size-xs);white-space:pre-wrap;word-break:break-word;line-height:1.6;background:none;border:none}`;
4273
+
4274
+ /** Breedte van de filterpopup in px — voor overflow-correctie. */
4275
+ const POPUP_WIDTH = 280;
3731
4276
  const MrdTable = class {
3732
4277
  constructor(hostRef) {
3733
4278
  index.registerInstance(this, hostRef);
@@ -3743,6 +4288,8 @@ const MrdTable = class {
3743
4288
  this.keydownHandler = null;
3744
4289
  this.createPickerClickHandler = null;
3745
4290
  this.viewPopoverClickHandler = null;
4291
+ /** Guards against scheduling more than one column-width measurement per freeze. */
4292
+ this.colWidthMeasureScheduled = false;
3746
4293
  // ── Props ──────────────────────────────────────────────────────────────────
3747
4294
  /** The VIEW or RELATED_VIEW layout item. Contains view config, dataClass, fromClass, actions etc. */
3748
4295
  this.item = null;
@@ -3799,13 +4346,10 @@ const MrdTable = class {
3799
4346
  this.minKnownTotal = 0;
3800
4347
  this.handleScroll = (e) => {
3801
4348
  const scroller = e.currentTarget;
3802
- const scrollTop = scroller.scrollTop;
3803
- const total = this.baseTotal;
3804
- const visStart = Math.floor(scrollTop / this.rowHeight);
3805
- const visEnd = Math.min(visStart + this.visibleCount(), total - 1);
3806
- this.scrollTop = scrollTop;
3807
- this.renderStart = Math.max(0, visStart - BUFFER);
3808
- this.renderEnd = Math.min(total - 1, visEnd + BUFFER);
4349
+ const { renderStart, renderEnd } = computeWindow(scroller.scrollTop, this.rowHeight, this.tableHeight, this.baseTotal);
4350
+ this.scrollTop = scroller.scrollTop;
4351
+ this.renderStart = renderStart;
4352
+ this.renderEnd = renderEnd;
3809
4353
  this.requestPagesForWindow(this.renderStart, this.renderEnd);
3810
4354
  };
3811
4355
  }
@@ -3827,16 +4371,9 @@ const MrdTable = class {
3827
4371
  }
3828
4372
  // ── Helpers ────────────────────────────────────────────────────────────────
3829
4373
  applyDefaultSort(defaultSort) {
3830
- var _a;
3831
- if (defaultSort) {
3832
- const parts = defaultSort.split(',');
3833
- this.sortField = parts[0].trim();
3834
- this.sortDir = ((_a = parts[1]) === null || _a === void 0 ? void 0 : _a.trim()) === 'desc' ? 'desc' : 'asc';
3835
- }
3836
- else {
3837
- this.sortField = '';
3838
- this.sortDir = 'asc';
3839
- }
4374
+ const { field, dir } = parseDefaultSort(defaultSort);
4375
+ this.sortField = field;
4376
+ this.sortDir = dir;
3840
4377
  }
3841
4378
  // ── Public API ─────────────────────────────────────────────────────────────
3842
4379
  /**
@@ -3853,6 +4390,7 @@ const MrdTable = class {
3853
4390
  this.loadedPages = new Map();
3854
4391
  this.requestedPages = new Set();
3855
4392
  this.colWidths = [];
4393
+ this.colWidthMeasureScheduled = false;
3856
4394
  this.scrollTop = 0;
3857
4395
  this.renderStart = 0;
3858
4396
  // Always fill the visible viewport on init — totalElements may be stale from a
@@ -3933,21 +4471,34 @@ const MrdTable = class {
3933
4471
  }
3934
4472
  }
3935
4473
  componentDidRender() {
3936
- if (this.colWidths.length === 0 && this.loadedPages.size > 0 && this.totalElements > 0) {
3937
- const ths = this.el.querySelectorAll('.mrd-table__header');
3938
- if (ths.length > 0) {
3939
- this.colWidths = Array.from(ths).map(th => th.offsetWidth);
3940
- }
4474
+ // Freeze header widths once the first data page has rendered. The measurement
4475
+ // reads offsetWidth and writes the colWidths @State, which would trigger a
4476
+ // re-render *during* the render cycle if done synchronously here. Defer it to a
4477
+ // writeTask so the state mutation happens outside the render pass (avoids the
4478
+ // Stencil "state/prop changed during rendering" warning and potential loops).
4479
+ if (this.colWidths.length === 0 &&
4480
+ !this.colWidthMeasureScheduled &&
4481
+ this.loadedPages.size > 0 &&
4482
+ this.totalElements > 0) {
4483
+ this.colWidthMeasureScheduled = true;
4484
+ index.writeTask(() => {
4485
+ this.colWidthMeasureScheduled = false;
4486
+ // Re-check: state may have changed (e.g. a reset) between scheduling and running.
4487
+ if (this.colWidths.length !== 0)
4488
+ return;
4489
+ const ths = this.el.querySelectorAll('.mrd-table__header');
4490
+ if (ths.length > 0) {
4491
+ this.colWidths = Array.from(ths).map(th => th.offsetWidth);
4492
+ }
4493
+ });
3941
4494
  }
3942
4495
  }
3943
4496
  // ── Paging / scroll helpers ────────────────────────────────────────────────
3944
4497
  visibleCount() {
3945
- return Math.ceil(this.tableHeight / this.rowHeight);
4498
+ return visibleCount(this.tableHeight, this.rowHeight);
3946
4499
  }
3947
4500
  sortParam() {
3948
- if (!this.sortField)
3949
- return '';
3950
- return this.sortDir === 'desc' ? `${this.sortField},desc` : this.sortField;
4501
+ return buildSortParam(this.sortField, this.sortDir);
3951
4502
  }
3952
4503
  /** Stable ordered list: primary view first, then alternatives (from the item prop). */
3953
4504
  get allViews() {
@@ -3973,14 +4524,16 @@ const MrdTable = class {
3973
4524
  * VIEW: /excel/{dataClass}
3974
4525
  * RELATED_VIEW: /excel/{fromClass}/{parentId}/{dataClass} */
3975
4526
  buildExcelPath() {
3976
- var _a, _b, _c, _d;
4527
+ var _a;
3977
4528
  const v = this.allViews[this.activeViewIdx];
3978
4529
  if (!v)
3979
4530
  return '';
3980
- if (((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === 'RELATED_VIEW') {
3981
- return `/excel/${(_b = v.fromClass) !== null && _b !== void 0 ? _b : ''}/${this.parentId}/${(_c = v.dataClass) !== null && _c !== void 0 ? _c : ''}`;
3982
- }
3983
- return `/excel/${(_d = v.dataClass) !== null && _d !== void 0 ? _d : ''}`;
4531
+ return '/excel' + buildListPath({
4532
+ isRelatedView: ((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === 'RELATED_VIEW',
4533
+ fromClass: v.fromClass,
4534
+ parentId: this.parentId,
4535
+ dataClass: v.dataClass,
4536
+ });
3984
4537
  }
3985
4538
  buildActionDetail(action, basicType) {
3986
4539
  var _a, _b, _c;
@@ -4000,80 +4553,28 @@ const MrdTable = class {
4000
4553
  * VIEW: /{dataClass}
4001
4554
  * RELATED_VIEW: /{fromClass}/{parentId}/{dataClass} */
4002
4555
  buildDataPath() {
4003
- var _a, _b, _c, _d;
4556
+ var _a;
4004
4557
  const v = this.allViews[this.activeViewIdx];
4005
4558
  if (!v)
4006
4559
  return '';
4007
- if (((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === 'RELATED_VIEW') {
4008
- return `/${(_b = v.fromClass) !== null && _b !== void 0 ? _b : ''}/${this.parentId}/${(_c = v.dataClass) !== null && _c !== void 0 ? _c : ''}`;
4009
- }
4010
- return `/${(_d = v.dataClass) !== null && _d !== void 0 ? _d : ''}`;
4560
+ return buildListPath({
4561
+ isRelatedView: ((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === 'RELATED_VIEW',
4562
+ fromClass: v.fromClass,
4563
+ parentId: this.parentId,
4564
+ dataClass: v.dataClass,
4565
+ });
4011
4566
  }
4012
4567
  /** Build query params for a page request from current sort, view filters, filterClass and active column filters. */
4013
4568
  buildQueryParams(page) {
4014
- var _a, _b, _c, _d, _e, _f, _g;
4569
+ var _a;
4015
4570
  const v = this.allViews[this.activeViewIdx];
4016
- const p = new URLSearchParams();
4017
- if (page > 0)
4018
- p.set('page', String(page));
4019
- const sort = this.sortParam();
4020
- if (sort)
4021
- p.set('sort', sort);
4022
- const filterClass = v === null || v === void 0 ? void 0 : v.filterClass;
4023
- if (filterClass)
4024
- p.set('type', filterClass);
4025
- for (const f of ((_b = (_a = v === null || v === void 0 ? void 0 : v.view) === null || _a === void 0 ? void 0 : _a.filter) !== null && _b !== void 0 ? _b : [])) {
4026
- if (!f.name)
4027
- continue;
4028
- if (f.operator === 'EMPTY') {
4029
- p.set(f.name, '');
4030
- continue;
4031
- }
4032
- if (f.operator === 'NOT_EMPTY') {
4033
- p.set(f.name + '_notempty', 'true');
4034
- continue;
4035
- }
4036
- if (f.operator === 'STARTS_WITH') {
4037
- p.set(f.name + '_startswith', String((_c = f.value) !== null && _c !== void 0 ? _c : ''));
4038
- continue;
4039
- }
4040
- if (f.operator === 'FROM') {
4041
- p.set(f.name + '_from', String((_d = f.value) !== null && _d !== void 0 ? _d : ''));
4042
- continue;
4043
- }
4044
- if (f.operator === 'TO') {
4045
- p.set(f.name + '_to', String((_e = f.value) !== null && _e !== void 0 ? _e : ''));
4046
- continue;
4047
- }
4048
- if (f.value != null) {
4049
- p.set(f.name, String(f.value));
4050
- }
4051
- }
4052
- for (const f of this.activeFilters.values()) {
4053
- if (f.operator === 'isEmpty') {
4054
- p.set(f.field, '');
4055
- continue;
4056
- }
4057
- if (f.operator === 'isNotEmpty') {
4058
- p.set(f.field + '_notempty', 'true');
4059
- continue;
4060
- }
4061
- if (f.operator === 'startsWith') {
4062
- p.set(f.field + '_startswith', String((_f = f.value) !== null && _f !== void 0 ? _f : ''));
4063
- continue;
4064
- }
4065
- if ((_g = f.values) === null || _g === void 0 ? void 0 : _g.length) {
4066
- p.set(f.field, f.values.join(','));
4067
- continue;
4068
- }
4069
- if (f.value != null)
4070
- p.set(f.field, String(f.value));
4071
- if (f.from != null)
4072
- p.set(f.field + '_from', String(f.from));
4073
- if (f.to != null)
4074
- p.set(f.field + '_to', String(f.to));
4075
- }
4076
- return p.toString();
4571
+ return buildTableQueryParams({
4572
+ page,
4573
+ sort: this.sortParam(),
4574
+ filterClass: v === null || v === void 0 ? void 0 : v.filterClass,
4575
+ viewFilters: (_a = v === null || v === void 0 ? void 0 : v.view) === null || _a === void 0 ? void 0 : _a.filter,
4576
+ activeFilters: this.activeFilters.values(),
4577
+ });
4077
4578
  }
4078
4579
  get columns() {
4079
4580
  var _a, _b, _c;
@@ -4128,11 +4629,7 @@ const MrdTable = class {
4128
4629
  isTotalKnown() {
4129
4630
  if (this.aggregationsTotal != null)
4130
4631
  return true;
4131
- for (const rows of this.loadedPages.values()) {
4132
- if (rows.length < this.pageSize)
4133
- return true;
4134
- }
4135
- return false;
4632
+ return isTotalKnownFromPages(this.loadedPages, this.pageSize);
4136
4633
  }
4137
4634
  /** Effective total: aggregations-response > totalElements prop > minKnownTotal from setPage(). */
4138
4635
  get baseTotal() {
@@ -4143,61 +4640,9 @@ const MrdTable = class {
4143
4640
  return this.minKnownTotal;
4144
4641
  }
4145
4642
  // ── Aggregation helpers ────────────────────────────────────────────────────
4146
- buildAggregationParams() {
4147
- var _a;
4148
- const groups = { sum: [], avg: [], count: [] };
4149
- for (const col of this.columns) {
4150
- if (col.type !== 'FIELD' || !col.aggregate)
4151
- continue;
4152
- const fn = col.aggregate.toLowerCase();
4153
- if (fn in groups)
4154
- groups[fn].push((_a = col.name) !== null && _a !== void 0 ? _a : '');
4155
- }
4156
- const params = {};
4157
- if (groups.sum.length)
4158
- params.sum = groups.sum;
4159
- if (groups.avg.length)
4160
- params.avg = groups.avg;
4161
- if (groups.count.length)
4162
- params.count = groups.count;
4163
- return Object.keys(params).length > 0 ? params : null;
4164
- }
4165
- buildAggregationQs() {
4166
- var _a, _b, _c;
4167
- const p = new URLSearchParams(this.buildQueryParams(0));
4168
- p.delete('page');
4169
- p.delete('sort');
4170
- const groups = this.buildAggregationParams();
4171
- if ((_a = groups === null || groups === void 0 ? void 0 : groups.sum) === null || _a === void 0 ? void 0 : _a.length)
4172
- p.set('sum', groups.sum.join(','));
4173
- if ((_b = groups === null || groups === void 0 ? void 0 : groups.avg) === null || _b === void 0 ? void 0 : _b.length)
4174
- p.set('avg', groups.avg.join(','));
4175
- if ((_c = groups === null || groups === void 0 ? void 0 : groups.count) === null || _c === void 0 ? void 0 : _c.length)
4176
- p.set('count', groups.count.join(','));
4177
- return p.toString();
4178
- }
4179
4643
  emitLoadAggregations() {
4180
- this.mrdLoadAggregations.emit({ path: this.buildDataPath(), qs: this.buildQueryParams(0), aggQs: this.buildAggregationQs() });
4181
- }
4182
- renderAggregationValue(col) {
4183
- var _a;
4184
- if (col.type !== 'FIELD' || !col.aggregate || !this.aggregations)
4185
- return '';
4186
- const fn = col.aggregate.toLowerCase();
4187
- const aggData = this.aggregations[fn];
4188
- const val = typeof aggData === 'object' && aggData !== null
4189
- ? aggData[(_a = col.name) !== null && _a !== void 0 ? _a : '']
4190
- : undefined;
4191
- if (val == null)
4192
- return '';
4193
- const dt = col.dataType;
4194
- if (dt === 'INTEGER')
4195
- return formatNumber(val, this.locale, { maximumFractionDigits: 0 });
4196
- if (dt === 'PERCENTAGE')
4197
- return formatPercentage(val, this.locale);
4198
- if (dt === 'CURRENCY' && col.currencyCode)
4199
- return formatCurrency(val, col.currencyCode, this.locale);
4200
- return formatNumber(val, this.locale);
4644
+ const qs = this.buildQueryParams(0);
4645
+ this.mrdLoadAggregations.emit({ path: this.buildDataPath(), qs, aggQs: buildAggregationQs(qs, this.columns) });
4201
4646
  }
4202
4647
  // ── Reset pagination ───────────────────────────────────────────────────────
4203
4648
  /** Reset pagination state and scroll to top (used after sort or filter change). */
@@ -4210,6 +4655,7 @@ const MrdTable = class {
4210
4655
  this.loadedPages = new Map();
4211
4656
  this.requestedPages = new Set();
4212
4657
  this.colWidths = [];
4658
+ this.colWidthMeasureScheduled = false;
4213
4659
  this.scrollTop = 0;
4214
4660
  this.renderStart = 0;
4215
4661
  this.minKnownTotal = 0;
@@ -4239,8 +4685,7 @@ const MrdTable = class {
4239
4685
  this.emitPagesForWindow(this.renderStart, this.renderEnd);
4240
4686
  }
4241
4687
  emitPagesForWindow(start, end) {
4242
- const firstPage = Math.floor(start / this.pageSize);
4243
- const lastPage = Math.floor(end / this.pageSize);
4688
+ const { firstPage, lastPage } = pageRange(start, end, this.pageSize);
4244
4689
  const next = new Set(this.requestedPages);
4245
4690
  let changed = false;
4246
4691
  for (let p = firstPage; p <= lastPage; p++) {
@@ -4254,13 +4699,10 @@ const MrdTable = class {
4254
4699
  this.requestedPages = next;
4255
4700
  }
4256
4701
  getRow(i) {
4257
- var _a;
4258
- const page = this.loadedPages.get(Math.floor(i / this.pageSize));
4259
- return (_a = page === null || page === void 0 ? void 0 : page[i % this.pageSize]) !== null && _a !== void 0 ? _a : null;
4702
+ return getRowFromPages(this.loadedPages, i, this.pageSize);
4260
4703
  }
4261
4704
  requestPagesForWindow(start, end) {
4262
- const firstPage = Math.floor(start / this.pageSize);
4263
- const lastPage = Math.floor(end / this.pageSize);
4705
+ const { firstPage, lastPage } = pageRange(start, end, this.pageSize);
4264
4706
  let anyNew = false;
4265
4707
  for (let p = firstPage; p <= lastPage; p++) {
4266
4708
  if (!this.loadedPages.has(p) && !this.requestedPages.has(p) && !this.pendingPages.has(p)) {
@@ -4322,17 +4764,7 @@ const MrdTable = class {
4322
4764
  // If from and to cover the same local day it was an exact-date filter — restore
4323
4765
  // to exact mode so the user sees the single-date input again.
4324
4766
  if (dataType === 'DATETIME' && existing && existing.operator !== 'isEmpty' && existing.operator !== 'isNotEmpty') {
4325
- const display = Object.assign({}, existing);
4326
- if (typeof display.from === 'string' && display.from)
4327
- display.from = this.utcISOToLocalDate(display.from);
4328
- if (typeof display.to === 'string' && display.to)
4329
- display.to = this.utcISOToLocalDateExclusiveEnd(display.to);
4330
- if (display.from && display.to && display.from === display.to) {
4331
- this.pendingFilter = Object.assign(Object.assign({}, display), { value: display.from, from: undefined, to: undefined });
4332
- }
4333
- else {
4334
- this.pendingFilter = display;
4335
- }
4767
+ this.pendingFilter = datetimeFilterToDisplay(existing);
4336
4768
  }
4337
4769
  else {
4338
4770
  this.pendingFilter = existing ? Object.assign({}, existing) : { field: name, dataType, operator: defaultOperator };
@@ -4398,81 +4830,15 @@ const MrdTable = class {
4398
4830
  const current = (_b = (_a = this.pendingFilter) === null || _a === void 0 ? void 0 : _a.values) !== null && _b !== void 0 ? _b : [];
4399
4831
  this.pendingFilter = Object.assign(Object.assign({}, this.pendingFilter), { values: checked ? [...current, key] : current.filter(k => k !== key) });
4400
4832
  }
4401
- filterHasValue(f) {
4402
- if (f.operator === 'isEmpty' || f.operator === 'isNotEmpty')
4403
- return true;
4404
- if (f.values !== undefined && f.values.length > 0)
4405
- return true;
4406
- if (f.value != null && f.value !== '')
4407
- return true;
4408
- if (typeof f.value === 'boolean')
4409
- return true;
4410
- if (f.from != null && f.from !== '')
4411
- return true;
4412
- if (f.to != null && f.to !== '')
4413
- return true;
4414
- return false;
4415
- }
4416
- // Convert a local "YYYY-MM-DD" date string to the UTC ISO string at the
4417
- // start of that local day (midnight). new Date(y, m, d) uses local time.
4418
- dateLocalToUTCStart(dateStr) {
4419
- if (!dateStr)
4420
- return dateStr;
4421
- const [year, month, day] = dateStr.split('-').map(Number);
4422
- return new Date(year, month - 1, day).toISOString().replace(/\.\d{3}Z$/, 'Z');
4423
- }
4424
- // Start of the day AFTER the given local date (exclusive range end).
4425
- dateLocalToUTCEndExclusive(dateStr) {
4426
- if (!dateStr)
4427
- return dateStr;
4428
- const [year, month, day] = dateStr.split('-').map(Number);
4429
- return new Date(year, month - 1, day + 1).toISOString().replace(/\.\d{3}Z$/, 'Z');
4430
- }
4431
- // Convert a stored UTC ISO string back to the local "YYYY-MM-DD" date.
4432
- utcISOToLocalDate(utcStr) {
4433
- if (!utcStr)
4434
- return utcStr;
4435
- const d = new Date(utcStr);
4436
- if (isNaN(d.getTime()))
4437
- return utcStr;
4438
- return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
4439
- }
4440
- // The stored "to" value is the exclusive end (midnight of the next day).
4441
- // Subtract one day to recover the local date the user entered.
4442
- utcISOToLocalDateExclusiveEnd(utcStr) {
4443
- if (!utcStr)
4444
- return utcStr;
4445
- const d = new Date(utcStr);
4446
- if (isNaN(d.getTime()))
4447
- return utcStr;
4448
- d.setDate(d.getDate() - 1);
4449
- return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
4450
- }
4451
4833
  applyFilter() {
4452
4834
  const f = this.pendingFilter;
4453
4835
  if (!(f === null || f === void 0 ? void 0 : f.field)) {
4454
4836
  this.closeFilterPopup();
4455
4837
  return;
4456
4838
  }
4457
- // For DATETIME fields the user enters local dates; convert to UTC ISO strings.
4458
- // Exact date → range covering the full local day (from = midnight, to = next midnight).
4459
- // "to" is always the exclusive end (midnight of the next local day).
4460
- let normalized = Object.assign({}, f);
4461
- if (f.dataType === 'DATETIME' && f.operator !== 'isEmpty' && f.operator !== 'isNotEmpty') {
4462
- if (typeof normalized.value === 'string' && normalized.value) {
4463
- normalized.from = this.dateLocalToUTCStart(normalized.value);
4464
- normalized.to = this.dateLocalToUTCEndExclusive(normalized.value);
4465
- normalized.value = undefined;
4466
- }
4467
- else {
4468
- if (typeof normalized.from === 'string' && normalized.from)
4469
- normalized.from = this.dateLocalToUTCStart(normalized.from);
4470
- if (typeof normalized.to === 'string' && normalized.to)
4471
- normalized.to = this.dateLocalToUTCEndExclusive(normalized.to);
4472
- }
4473
- }
4839
+ const normalized = normalizeDatetimeFilter(f);
4474
4840
  const next = new Map(this.activeFilters);
4475
- if (this.filterHasValue(normalized)) {
4841
+ if (filterHasValue(normalized)) {
4476
4842
  next.set(normalized.field, normalized);
4477
4843
  }
4478
4844
  else {
@@ -4527,140 +4893,53 @@ const MrdTable = class {
4527
4893
  toggleViewPopover(e) {
4528
4894
  e.stopPropagation();
4529
4895
  if (this.viewPopoverOpen) {
4530
- this.viewPopoverOpen = false;
4531
- if (this.viewPopoverClickHandler) {
4532
- document.removeEventListener('click', this.viewPopoverClickHandler);
4533
- this.viewPopoverClickHandler = null;
4534
- }
4896
+ this.closeViewPopover();
4535
4897
  return;
4536
4898
  }
4537
4899
  this.viewPopoverOpen = true;
4538
- this.viewPopoverClickHandler = () => {
4539
- this.viewPopoverOpen = false;
4900
+ this.viewPopoverClickHandler = () => this.closeViewPopover();
4901
+ document.addEventListener('click', this.viewPopoverClickHandler);
4902
+ }
4903
+ closeViewPopover() {
4904
+ this.viewPopoverOpen = false;
4905
+ if (this.viewPopoverClickHandler) {
4540
4906
  document.removeEventListener('click', this.viewPopoverClickHandler);
4541
4907
  this.viewPopoverClickHandler = null;
4542
- };
4543
- document.addEventListener('click', this.viewPopoverClickHandler);
4908
+ }
4544
4909
  }
4545
4910
  // ── Render: toolbar ────────────────────────────────────────────────────────
4546
4911
  renderToolbar() {
4547
4912
  var _a;
4548
- const filterCount = this.activeFilters.size;
4549
- const actions = this.tableActions;
4550
- const allViews = this.allViews;
4551
- const hasActions = actions.length > 0;
4552
- const hasViewSwitcher = allViews.length > 1;
4553
- return (index.h("div", { class: "mrd-table__toolbar" }, index.h("div", { class: "mrd-table__toolbar-left" }, index.h("button", { class: `mrd-table__action mrd-table__action--secondary mrd-table__filter-toggle${this.filterMode ? ' mrd-table__filter-toggle--active' : ''}`, onClick: () => this.handleFilterToggle() }, index.h("svg", { class: "mrd-table__action-icon", viewBox: "0 0 24 24", "aria-hidden": "true" }, index.h("path", { fill: "currentColor", d: "M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z" })), filterCount > 0 && index.h("span", { class: "mrd-table__filter-badge" }, filterCount), index.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 && (index.h("button", { class: "mrd-table__action mrd-table__action--secondary", onClick: () => this.clearAllFilters() }, index.h("svg", { class: "mrd-table__action-icon", viewBox: "0 0 24 24", "aria-hidden": "true" }, index.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" })), index.h("span", { class: "mrd-table__action-tooltip" }, t('table_filter_clear_all', this.locale))))), hasViewSwitcher && (index.h("div", { class: "mrd-table__toolbar-center" }, index.h("div", { class: "mrd-table__view-switcher" }, index.h("button", { class: "mrd-table__view-arrow", "aria-label": "Previous view", onClick: () => this.handleViewSwitch((this.activeViewIdx - 1 + allViews.length) % allViews.length) }, "\u25C0"), index.h("div", { class: "mrd-table__view-title-wrap" }, index.h("button", { class: "mrd-table__view-title", onClick: (e) => this.toggleViewPopover(e) }, (_a = allViews[this.activeViewIdx]) === null || _a === void 0 ? void 0 : _a.label), this.viewPopoverOpen && (index.h("div", { class: "mrd-table__view-popover", onClick: (e) => e.stopPropagation() }, allViews.map((v, i) => (index.h("button", { key: String(i), class: `mrd-table__view-popover-item${i === this.activeViewIdx ? ' mrd-table__view-popover-item--active' : ''}`, onClick: () => {
4554
- if (i !== this.activeViewIdx)
4555
- this.handleViewSwitch(i);
4556
- this.viewPopoverOpen = false;
4557
- if (this.viewPopoverClickHandler) {
4558
- document.removeEventListener('click', this.viewPopoverClickHandler);
4559
- this.viewPopoverClickHandler = null;
4560
- }
4561
- } }, v.label)))))), index.h("button", { class: "mrd-table__view-arrow", "aria-label": "Next view", onClick: () => this.handleViewSwitch((this.activeViewIdx + 1) % allViews.length) }, "\u25B6")))), hasActions && (index.h("div", { class: "mrd-table__toolbar-right" }, actions.map(a => {
4562
- var _a, _b, _c;
4563
- const createTypes = a.action === 'create' ? (_a = this.item) === null || _a === void 0 ? void 0 : _a.createTypes : null;
4564
- if (createTypes === null || createTypes === void 0 ? void 0 : createTypes.length) {
4565
- return (index.h("div", { class: "mrd-table__create-picker-wrap", key: `action-${a.action}` }, index.h("button", { class: `mrd-table__action mrd-table__action--${(_b = a.variant) !== null && _b !== void 0 ? _b : 'secondary'}`, onClick: () => this.toggleCreatePicker() }, a.icon
4566
- ? index.h("svg", { class: "mrd-table__action-icon", "aria-hidden": "true" }, index.h("use", { href: a.icon }))
4567
- : a.label, index.h("span", { class: "mrd-table__action-tooltip" }, a.label)), this.createPickerOpen && (index.h("div", { class: "mrd-table__create-picker" }, createTypes.map(ct => (index.h("button", { key: ct.type, class: "mrd-table__create-picker-item", onClick: () => {
4568
- this.mrdAction.emit(this.buildActionDetail('create', ct.type));
4569
- this.closeCreatePicker();
4570
- } }, ct.label)))))));
4571
- }
4572
- return (index.h("button", { key: `action-${a.action}`, class: `mrd-table__action mrd-table__action--${(_c = a.variant) !== null && _c !== void 0 ? _c : 'secondary'}`, disabled: a.disabled, onClick: () => this.mrdAction.emit(this.buildActionDetail(a.action)) }, a.icon
4573
- ? index.h("svg", { class: "mrd-table__action-icon", "aria-hidden": "true" }, index.h("use", { href: a.icon }))
4574
- : a.label, index.h("span", { class: "mrd-table__action-tooltip" }, a.label)));
4575
- })))));
4913
+ return (index.h(Toolbar, { locale: this.locale, filterMode: this.filterMode, filterCount: this.activeFilters.size, actions: this.tableActions, views: this.allViews, activeViewIdx: this.activeViewIdx, viewPopoverOpen: this.viewPopoverOpen, createPickerOpen: this.createPickerOpen, createTypes: (_a = this.item) === null || _a === void 0 ? void 0 : _a.createTypes, cb: {
4914
+ onFilterToggle: () => this.handleFilterToggle(),
4915
+ onClearAllFilters: () => this.clearAllFilters(),
4916
+ onViewSwitch: idx => this.handleViewSwitch(idx),
4917
+ onToggleViewPopover: e => this.toggleViewPopover(e),
4918
+ onCloseViewPopover: () => this.closeViewPopover(),
4919
+ onToggleCreatePicker: () => this.toggleCreatePicker(),
4920
+ onCreate: basicType => {
4921
+ this.mrdAction.emit(this.buildActionDetail('create', basicType));
4922
+ this.closeCreatePicker();
4923
+ },
4924
+ onAction: action => this.mrdAction.emit(this.buildActionDetail(action)),
4925
+ } }));
4576
4926
  }
4577
4927
  // ── Render: filter popup ───────────────────────────────────────────────────
4578
- renderFilterEditor(col) {
4579
- var _a, _b, _c, _d, _e, _f, _g;
4580
- const pf = (_a = this.pendingFilter) !== null && _a !== void 0 ? _a : {};
4581
- const dataType = this.colDataType(col);
4582
- if (NO_FILTER_TYPES.has(dataType)) {
4583
- return index.h("p", { class: "mrd-table__filter-no-support" }, t('filter_no_support', this.locale));
4584
- }
4585
- if (dataType === 'BOOLEAN') {
4586
- const boolOp = pf.operator;
4587
- const noValueOp = boolOp === 'isEmpty' || boolOp === 'isNotEmpty';
4588
- return (index.h("div", { class: "mrd-table__filter-radio-group" }, [
4589
- { labelKey: 'filter_all', value: null },
4590
- { labelKey: 'yes', value: true },
4591
- { labelKey: 'no', value: false },
4592
- ].map(opt => (index.h("label", { class: "mrd-table__filter-radio-label" }, index.h("input", { type: "radio", name: `bf-${this.openFilterCol}`, checked: !noValueOp && pf.value === opt.value, onChange: () => { this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: undefined, value: opt.value }); } }), t(opt.labelKey, this.locale)))), index.h("label", { class: "mrd-table__filter-radio-label" }, index.h("input", { type: "radio", name: `bf-${this.openFilterCol}`, checked: boolOp === 'isEmpty', onChange: () => { this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: 'isEmpty', value: undefined }); } }), t('filter_is_empty', this.locale)), index.h("label", { class: "mrd-table__filter-radio-label" }, index.h("input", { type: "radio", name: `bf-${this.openFilterCol}`, checked: boolOp === 'isNotEmpty', onChange: () => { this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: 'isNotEmpty', value: undefined }); } }), t('filter_is_not_empty', this.locale))));
4593
- }
4594
- if (dataType === 'LIST') {
4595
- const items = (_b = col.listItems) !== null && _b !== void 0 ? _b : [];
4596
- const selected = (_c = pf.values) !== null && _c !== void 0 ? _c : [];
4597
- return (index.h("div", { class: "mrd-table__filter-list" }, index.h("div", { class: "mrd-table__filter-list-controls" }, index.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)), index.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 => (index.h("label", { class: "mrd-table__filter-checkbox-label" }, index.h("input", { type: "checkbox", checked: selected.includes(item.key), onChange: (e) => this.togglePendingValue(item.key, e.target.checked) }), item.label)))));
4598
- }
4599
- if (TEXT_TYPES.has(dataType) || dataType === 'RELATION') {
4600
- const op = (_d = pf.operator) !== null && _d !== void 0 ? _d : 'startsWith';
4601
- const noInput = op === 'isEmpty' || op === 'isNotEmpty';
4602
- return (index.h("div", { class: "mrd-table__filter-editor" }, index.h("select", { class: "mrd-table__filter-select", onChange: (e) => this.setPending('operator', e.target.value) }, [
4603
- { val: 'startsWith', labelKey: 'filter_starts_with' },
4604
- { val: 'equals', labelKey: 'filter_equals' },
4605
- { val: 'isEmpty', labelKey: 'filter_is_empty' },
4606
- { val: 'isNotEmpty', labelKey: 'filter_is_not_empty' },
4607
- ].map(o => index.h("option", { value: o.val, selected: op === o.val }, t(o.labelKey, this.locale)))), !noInput && (index.h("input", { type: "text", class: "mrd-table__filter-input", value: String((_e = pf.value) !== null && _e !== void 0 ? _e : ''), placeholder: t('filter_search_value', this.locale), onInput: (e) => this.setPending('value', e.target.value) }))));
4608
- }
4609
- if (NUMERIC_TYPES.has(dataType)) {
4610
- const numOp = pf.operator;
4611
- const noInput = numOp === 'isEmpty' || numOp === 'isNotEmpty';
4612
- const rangeMode = !noInput && (pf.from !== undefined || pf.to !== undefined);
4613
- return (index.h("div", { class: "mrd-table__filter-editor" }, index.h("select", { class: "mrd-table__filter-select", onChange: (e) => {
4614
- const val = e.target.value;
4615
- if (val === 'isEmpty' || val === 'isNotEmpty') {
4616
- this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: val, value: undefined, from: undefined, to: undefined });
4617
- }
4618
- else {
4619
- this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: undefined });
4620
- }
4621
- } }, index.h("option", { value: "", selected: !noInput }, t('filter_has_value', this.locale)), index.h("option", { value: "isEmpty", selected: numOp === 'isEmpty' }, t('filter_is_empty', this.locale)), index.h("option", { value: "isNotEmpty", selected: numOp === 'isNotEmpty' }, t('filter_is_not_empty', this.locale))), !noInput && (index.h("div", { class: "mrd-table__filter-editor" }, index.h("div", { class: "mrd-table__filter-radio-group mrd-table__filter-radio-group--inline" }, index.h("label", { class: "mrd-table__filter-radio-label" }, index.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)), index.h("label", { class: "mrd-table__filter-radio-label" }, index.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 ? (index.h("input", { type: "number", class: "mrd-table__filter-input", value: pf.value != null ? String(pf.value) : '', onInput: (e) => this.setPending('value', e.target.value) })) : (index.h("div", { class: "mrd-table__filter-range" }, index.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) }), index.h("span", { class: "mrd-table__filter-range-sep" }, "\u2013"), index.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) })))))));
4622
- }
4623
- if (dataType === 'DATETIME') {
4624
- const dtOp = pf.operator;
4625
- const noInput = dtOp === 'isEmpty' || dtOp === 'isNotEmpty';
4626
- const rangeMode = !noInput && (pf.from !== undefined || pf.to !== undefined);
4627
- return (index.h("div", { class: "mrd-table__filter-editor" }, index.h("select", { class: "mrd-table__filter-select", onChange: (e) => {
4628
- const val = e.target.value;
4629
- if (val === 'isEmpty' || val === 'isNotEmpty') {
4630
- this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: val, value: undefined, from: undefined, to: undefined });
4631
- }
4632
- else {
4633
- this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: undefined });
4634
- }
4635
- } }, index.h("option", { value: "", selected: !noInput }, t('filter_has_value', this.locale)), index.h("option", { value: "isEmpty", selected: dtOp === 'isEmpty' }, t('filter_is_empty', this.locale)), index.h("option", { value: "isNotEmpty", selected: dtOp === 'isNotEmpty' }, t('filter_is_not_empty', this.locale))), !noInput && (index.h("div", { class: "mrd-table__filter-editor" }, index.h("div", { class: "mrd-table__filter-radio-group mrd-table__filter-radio-group--inline" }, index.h("label", { class: "mrd-table__filter-radio-label" }, index.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)), index.h("label", { class: "mrd-table__filter-radio-label" }, index.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 ? (index.h("input", { type: "date", class: "mrd-table__filter-input", value: String((_f = pf.value) !== null && _f !== void 0 ? _f : ''), onInput: (e) => this.setPending('value', e.target.value) })) : (index.h("div", { class: "mrd-table__filter-range mrd-table__filter-range--stacked" }, index.h("label", { class: "mrd-table__filter-range-label" }, t('filter_from', this.locale)), index.h("input", { type: "date", class: "mrd-table__filter-input", value: pf.from != null ? String(pf.from) : '', onInput: (e) => this.setPending('from', e.target.value) }), index.h("label", { class: "mrd-table__filter-range-label" }, t('filter_to', this.locale)), index.h("input", { type: "date", class: "mrd-table__filter-input", value: pf.to != null ? String(pf.to) : '', onInput: (e) => this.setPending('to', e.target.value) })))))));
4636
- }
4637
- if (DATE_TYPES.has(dataType)) {
4638
- const inputType = dataType === 'DATE' ? 'date' : 'time';
4639
- const dtdOp = pf.operator;
4640
- const noInput = dtdOp === 'isEmpty' || dtdOp === 'isNotEmpty';
4641
- const rangeMode = !noInput && (pf.from !== undefined || pf.to !== undefined);
4642
- return (index.h("div", { class: "mrd-table__filter-editor" }, index.h("select", { class: "mrd-table__filter-select", onChange: (e) => {
4643
- const val = e.target.value;
4644
- if (val === 'isEmpty' || val === 'isNotEmpty') {
4645
- this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: val, value: undefined, from: undefined, to: undefined });
4646
- }
4647
- else {
4648
- this.pendingFilter = Object.assign(Object.assign({}, pf), { operator: undefined });
4649
- }
4650
- } }, index.h("option", { value: "", selected: !noInput }, t('filter_has_value', this.locale)), index.h("option", { value: "isEmpty", selected: dtdOp === 'isEmpty' }, t('filter_is_empty', this.locale)), index.h("option", { value: "isNotEmpty", selected: dtdOp === 'isNotEmpty' }, t('filter_is_not_empty', this.locale))), !noInput && (index.h("div", { class: "mrd-table__filter-editor" }, index.h("div", { class: "mrd-table__filter-radio-group mrd-table__filter-radio-group--inline" }, index.h("label", { class: "mrd-table__filter-radio-label" }, index.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)), index.h("label", { class: "mrd-table__filter-radio-label" }, index.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 ? (index.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) })) : (index.h("div", { class: "mrd-table__filter-range" }, index.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) }), index.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) })))))));
4651
- }
4652
- return null;
4653
- }
4654
4928
  renderFilterPopup() {
4655
- var _a;
4656
4929
  if (!this.openFilterCol || !this.pendingFilter)
4657
4930
  return null;
4658
4931
  const col = this.columns.find(c => this.colName(c) === this.openFilterCol);
4659
4932
  if (!col)
4660
4933
  return null;
4661
- const label = (_a = col.label) !== null && _a !== void 0 ? _a : this.openFilterCol;
4662
- const sortActive = this.sortField === this.openFilterCol;
4663
- return (index.h("div", { class: "mrd-table__filter-popup", style: { top: `${this.popupPos.top}px`, left: `${this.popupPos.left}px` }, onClick: (e) => e.stopPropagation() }, index.h("div", { class: "mrd-table__filter-popup-header" }, index.h("span", { class: "mrd-table__filter-popup-title" }, label), index.h("button", { class: "mrd-table__filter-close", onClick: () => this.closeFilterPopup() }, "\u2715")), index.h("div", { class: "mrd-table__filter-section" }, index.h("div", { class: "mrd-table__filter-section-label" }, t('filter_sorting', this.locale)), index.h("div", { class: "mrd-table__filter-sort-buttons" }, index.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)), index.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)))), index.h("div", { class: "mrd-table__filter-divider" }), index.h("div", { class: "mrd-table__filter-section" }, index.h("div", { class: "mrd-table__filter-section-label" }, t('filter_section', this.locale)), this.renderFilterEditor(col)), index.h("div", { class: "mrd-table__filter-popup-footer" }, index.h("button", { class: "mrd-table__filter-btn mrd-table__filter-btn--clear", onClick: () => this.clearFilter() }, t('filter_clear', this.locale)), index.h("button", { class: "mrd-table__filter-btn mrd-table__filter-btn--apply", onClick: () => this.applyFilter() }, t('filter_apply', this.locale)))));
4934
+ return (index.h(FilterPopup, { col: col, dataType: this.colDataType(col), openFilterCol: this.openFilterCol, pendingFilter: this.pendingFilter, popupPos: this.popupPos, sortField: this.sortField, sortDir: this.sortDir, locale: this.locale, cb: {
4935
+ onSetPending: (key, val) => this.setPending(key, val),
4936
+ onReplacePending: pf => (this.pendingFilter = pf),
4937
+ onToggleValue: (key, checked) => this.togglePendingValue(key, checked),
4938
+ onApplySort: dir => this.applySort(col, dir),
4939
+ onApply: () => this.applyFilter(),
4940
+ onClear: () => this.clearFilter(),
4941
+ onClose: () => this.closeFilterPopup(),
4942
+ } }));
4664
4943
  }
4665
4944
  // ── Render: footer ────────────────────────────────────────────────────────
4666
4945
  renderFooter(rowCount, effectiveTotal, isTotalKnown = true) {
@@ -4685,54 +4964,11 @@ const MrdTable = class {
4685
4964
  }
4686
4965
  // ── Render: cell ──────────────────────────────────────────────────────────
4687
4966
  renderCell(col, row) {
4688
- var _a, _b, _c;
4689
- const numericTypes = new Set(['INTEGER', 'DECIMAL', 'PERCENTAGE', 'CURRENCY']);
4690
- const dataType = (_a = col.dataType) !== null && _a !== void 0 ? _a : '';
4691
- const isNumeric = col.type === 'FIELD' && numericTypes.has(dataType);
4692
- const isFile = col.type === 'FIELD' && (dataType === 'FILE' || dataType === 'IMAGE');
4693
- if (isFile) {
4694
- const name = (_b = col.name) !== null && _b !== void 0 ? _b : '';
4695
- const fileVal = row === null || row === void 0 ? void 0 : row[name];
4696
- const href = fileVal === null || fileVal === void 0 ? void 0 : fileVal.href;
4697
- const fileName = fileVal === null || fileVal === void 0 ? void 0 : fileVal.fileName;
4698
- return (index.h("td", { class: "mrd-table__cell" }, href && fileName ? (index.h("button", { class: "mrd-table__file-btn", title: fileName, onClick: (e) => {
4699
- e.stopPropagation();
4700
- this.mrdDownload.emit({ href, fileName });
4701
- } }, index.h("svg", { class: "mrd-table__file-icon", viewBox: "0 0 24 24", "aria-hidden": "true" }, index.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))) : ''));
4702
- }
4703
- if (dataType === 'JSON') {
4704
- const name = (_c = col.name) !== null && _c !== void 0 ? _c : '';
4705
- const rawValue = name ? row === null || row === void 0 ? void 0 : row[name] : undefined;
4706
- if (rawValue == null || rawValue === '')
4707
- return index.h("td", { class: "mrd-table__cell" });
4708
- const compactHtml = CellRenderer.formatJson(rawValue, true);
4709
- const prettyHtml = CellRenderer.formatJson(rawValue, false);
4710
- return (index.h("td", { class: "mrd-table__cell" }, index.h("span", { class: "mrd-table__json-preview", innerHTML: compactHtml }), index.h("button", { class: "mrd-table__textblock-btn", onClick: (e) => { e.stopPropagation(); this.openJsonModal(prettyHtml); }, "aria-label": t('textblock_show_more', this.locale) }, "\u22EF")));
4711
- }
4712
- const TEXTBLOCK_MAX = 200;
4713
- if (dataType === 'TEXTBLOCK') {
4714
- const full = CellRenderer.render(col, row, this.locale);
4715
- if (full.length <= TEXTBLOCK_MAX) {
4716
- return index.h("td", { class: "mrd-table__cell" }, full);
4717
- }
4718
- const preview = full.slice(0, TEXTBLOCK_MAX) + '…';
4719
- return (index.h("td", { class: "mrd-table__cell" }, preview, index.h("button", { class: "mrd-table__textblock-btn", onClick: (e) => { e.stopPropagation(); this.openTextblockModal(full); }, "aria-label": t('textblock_show_more', this.locale) }, "\u22EF")));
4720
- }
4721
- const value = CellRenderer.render(col, row, this.locale);
4722
- return (index.h("td", { class: `mrd-table__cell${isNumeric ? ' mrd-table__cell--numeric' : ''}` }, value));
4967
+ return (index.h(TableCell, { col: col, row: row, locale: this.locale, onDownload: detail => this.mrdDownload.emit(detail), onOpenTextblock: full => this.openTextblockModal(full), onOpenJson: html => this.openJsonModal(html) }));
4723
4968
  }
4724
4969
  // ── Render: totals row ────────────────────────────────────────────────────
4725
4970
  renderTotalsRow() {
4726
- if (!this.aggregations)
4727
- return null;
4728
- if (!this.columns.some(c => c.type === 'FIELD' && c.aggregate))
4729
- return null;
4730
- return (index.h("tfoot", null, index.h("tr", { class: "mrd-table__totals-row" }, this.columns.map(col => {
4731
- var _a;
4732
- const val = this.renderAggregationValue(col);
4733
- const isNumeric = col.type === 'FIELD' && NUMERIC_TYPES.has((_a = col.dataType) !== null && _a !== void 0 ? _a : '');
4734
- return (index.h("td", { class: `mrd-table__totals-cell${isNumeric ? ' mrd-table__totals-cell--numeric' : ''}` }, val));
4735
- }))));
4971
+ return index.h(TotalsRow, { columns: this.columns, aggregations: this.aggregations, locale: this.locale });
4736
4972
  }
4737
4973
  // ── Render ─────────────────────────────────────────────────────────────────
4738
4974
  render() {
@@ -4752,7 +4988,7 @@ const MrdTable = class {
4752
4988
  isFiltered ? 'mrd-table__header--filtered' : '',
4753
4989
  this.filterMode ? 'mrd-table__header--sortable' : '',
4754
4990
  ].filter(Boolean).join(' ');
4755
- return (index.h("th", { class: cls, onClick: this.filterMode ? (e) => this.handleFilterOpen(col, e) : undefined }, index.h("span", { class: "mrd-table__header-label" }, (_a = col.label) !== null && _a !== void 0 ? _a : ''), isFiltered && this.renderFilterIcon()));
4991
+ return (index.h("th", { class: cls, onClick: this.filterMode ? (e) => this.handleFilterOpen(col, e) : undefined }, index.h("span", { class: "mrd-table__header-label" }, (_a = col.label) !== null && _a !== void 0 ? _a : ''), isFiltered && index.h(FilterIcon, null)));
4756
4992
  }))), index.h("tbody", null, (_b = this.rows) === null || _b === void 0 ? void 0 : _b.map((row, i) => (index.h("tr", { class: "mrd-table__row mrd-table__row--clickable", style: { background: i % 2 === 0 ? '' : 'var(--mrd-color-neutral-100)' }, onClick: () => this.mrdRowClick.emit(row) }, this.columns.map(col => this.renderCell(col, row)))))), this.renderTotalsRow()), (!this.rows || this.rows.length === 0) && (index.h("p", { class: "mrd-table__empty" }, t('no_results', this.locale)))), this.renderFooter((_c = this.rows) === null || _c === void 0 ? void 0 : _c.length), this.renderFilterPopup(), this.renderTextblockModal(), this.renderJsonModal()));
4757
4993
  }
4758
4994
  // ── Paginated / virtual-scroll mode ────────────────────────────────────
@@ -4760,12 +4996,7 @@ const MrdTable = class {
4760
4996
  // if any loaded page is shorter than pageSize it is the last page,
4761
4997
  // so the true total cannot exceed (pageNum * pageSize + pageRows.length).
4762
4998
  // aggregationsTotal (from setAggregations) takes priority over the totalElements prop.
4763
- let effectiveTotal = this.baseTotal;
4764
- for (const [pageNum, pageRows] of this.loadedPages) {
4765
- if (pageRows.length < this.pageSize) {
4766
- effectiveTotal = Math.min(effectiveTotal, pageNum * this.pageSize + pageRows.length);
4767
- }
4768
- }
4999
+ const effectiveTotal = computeEffectiveTotal(this.loadedPages, this.pageSize, this.baseTotal);
4769
5000
  // Clamp renderEnd to what we actually know exists (-1 when empty)
4770
5001
  const clampedEnd = Math.min(this.renderEnd, effectiveTotal - 1);
4771
5002
  const colCount = this.columns.length;
@@ -4796,21 +5027,14 @@ const MrdTable = class {
4796
5027
  isActive ? `mrd-table__header--sorted-${this.sortDir}` : '',
4797
5028
  isFiltered ? 'mrd-table__header--filtered' : '',
4798
5029
  ].filter(Boolean).join(' ');
4799
- return (index.h("th", { class: cls, style: this.colWidths[idx] ? { width: `${this.colWidths[idx]}px` } : undefined, onClick: isInteractive ? ((e) => this.filterMode ? this.handleFilterOpen(col, e) : this.handleSortClick(col)) : undefined }, index.h("span", { class: "mrd-table__header-label" }, (_a = col.label) !== null && _a !== void 0 ? _a : ''), isInteractive && isActive && (index.h("span", { class: "mrd-table__sort-icon", "aria-hidden": "true" }, this.sortDir === 'asc' ? '▲' : '▼')), isInteractive && !isActive && !this.filterMode && (index.h("span", { class: "mrd-table__sort-icon", "aria-hidden": "true" }, "\u21C5")), isInteractive && isFiltered && this.renderFilterIcon()));
4800
- }))), index.h("tbody", null, topSpacerHeight > 0 && (index.h("tr", { class: "mrd-table__spacer", style: { height: `${topSpacerHeight}px` } }, index.h("td", { colSpan: colCount }))), renderedRows, bottomSpacerHeight > 0 && (index.h("tr", { class: "mrd-table__spacer", style: { height: `${bottomSpacerHeight}px` } }, index.h("td", { colSpan: colCount })))), this.renderTotalsRow())), effectiveTotal === 0 && this.loadedPages.has(0) && (index.h("p", { class: "mrd-table__empty" }, t('no_results', this.locale))), effectiveTotal > 0 && this.renderFooter(undefined, effectiveTotal, this.isTotalKnown()), this.renderFilterPopup(), this.renderTextblockModal()));
4801
- }
4802
- renderFilterIcon() {
4803
- return (index.h("span", { class: "mrd-table__filter-icon", "aria-hidden": "true" }, index.h("svg", { viewBox: "0 0 24 24", width: "14", height: "14", fill: "currentColor" }, index.h("path", { d: "M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z" }))));
5030
+ return (index.h("th", { class: cls, style: this.colWidths[idx] ? { width: `${this.colWidths[idx]}px` } : undefined, onClick: isInteractive ? ((e) => this.filterMode ? this.handleFilterOpen(col, e) : this.handleSortClick(col)) : undefined }, index.h("span", { class: "mrd-table__header-label" }, (_a = col.label) !== null && _a !== void 0 ? _a : ''), isInteractive && isActive && (index.h("span", { class: "mrd-table__sort-icon", "aria-hidden": "true" }, this.sortDir === 'asc' ? '▲' : '▼')), isInteractive && !isActive && !this.filterMode && (index.h("span", { class: "mrd-table__sort-icon", "aria-hidden": "true" }, "\u21C5")), isInteractive && isFiltered && index.h(FilterIcon, null)));
5031
+ }))), index.h("tbody", null, topSpacerHeight > 0 && (index.h("tr", { class: "mrd-table__spacer", style: { height: `${topSpacerHeight}px` } }, index.h("td", { colSpan: colCount }))), renderedRows, bottomSpacerHeight > 0 && (index.h("tr", { class: "mrd-table__spacer", style: { height: `${bottomSpacerHeight}px` } }, index.h("td", { colSpan: colCount })))), this.renderTotalsRow())), effectiveTotal === 0 && this.loadedPages.has(0) && (index.h("p", { class: "mrd-table__empty" }, t('no_results', this.locale))), effectiveTotal > 0 && this.renderFooter(undefined, effectiveTotal, this.isTotalKnown()), this.renderFilterPopup(), this.renderTextblockModal(), this.renderJsonModal()));
4804
5032
  }
4805
5033
  renderTextblockModal() {
4806
- if (this.textblockModal === null)
4807
- return null;
4808
- return (index.h("div", { class: "mrd-table__modal-backdrop", onClick: () => this.closeTextblockModal(), role: "dialog", "aria-modal": "true" }, index.h("div", { class: "mrd-table__modal", onClick: (e) => e.stopPropagation() }, index.h("button", { class: "mrd-table__modal-close", onClick: () => this.closeTextblockModal(), "aria-label": t('close', this.locale) }, "\u2715"), index.h("p", { class: "mrd-table__modal-text" }, this.textblockModal))));
5034
+ return index.h(TextblockModal, { text: this.textblockModal, locale: this.locale, onClose: () => this.closeTextblockModal() });
4809
5035
  }
4810
5036
  renderJsonModal() {
4811
- if (this.jsonModal === null)
4812
- return null;
4813
- return (index.h("div", { class: "mrd-table__modal-backdrop", onClick: () => this.closeJsonModal(), role: "dialog", "aria-modal": "true" }, index.h("div", { class: "mrd-table__modal", onClick: (e) => e.stopPropagation() }, index.h("button", { class: "mrd-table__modal-close", onClick: () => this.closeJsonModal(), "aria-label": t('close', this.locale) }, "\u2715"), index.h("pre", { class: "mrd-table__modal-json", innerHTML: this.jsonModal }))));
5037
+ return index.h(JsonModal, { html: this.jsonModal, locale: this.locale, onClose: () => this.closeJsonModal() });
4814
5038
  }
4815
5039
  get el() { return index.getElement(this); }
4816
5040
  static get watchers() { return {
@@ -4822,9 +5046,9 @@ const MrdTable = class {
4822
5046
  }]
4823
5047
  }; }
4824
5048
  };
4825
- MrdTable.style = mrdTableScss();
5049
+ MrdTable.style = mrdTableCss();
4826
5050
 
4827
- const mrdTextFieldScss = () => `.sc-mrd-text-field-h{display:block}.mrd-text-field.sc-mrd-text-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-text-field__label.sc-mrd-text-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-text-field__label--required.sc-mrd-text-field::after{content:' *';color:var(--mrd-color-danger)}.mrd-text-field__input.sc-mrd-text-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box}.mrd-text-field__input.sc-mrd-text-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-text-field__input.sc-mrd-text-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-text-field__input.sc-mrd-text-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-text-field__input--error.sc-mrd-text-field{border-color:var(--mrd-border-color-error)}.mrd-text-field__input--error.sc-mrd-text-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-text-field__error.sc-mrd-text-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}`;
5051
+ const mrdTextFieldCss = () => `.sc-mrd-text-field-h{display:block}.mrd-text-field.sc-mrd-text-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-text-field__label.sc-mrd-text-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-text-field__label--required.sc-mrd-text-field::after{content:" *";color:var(--mrd-color-danger)}.mrd-text-field__input.sc-mrd-text-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box}.mrd-text-field__input.sc-mrd-text-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-text-field__input.sc-mrd-text-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-text-field__input.sc-mrd-text-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-text-field__input--error.sc-mrd-text-field{border-color:var(--mrd-border-color-error)}.mrd-text-field__input--error.sc-mrd-text-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-text-field__error.sc-mrd-text-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}`;
4828
5052
 
4829
5053
  const MrdTextField = class {
4830
5054
  constructor(hostRef) {
@@ -4845,23 +5069,17 @@ const MrdTextField = class {
4845
5069
  };
4846
5070
  this.handleBlur = (e) => {
4847
5071
  const val = e.target.value;
4848
- if (this.required && !validateRequired(val)) {
4849
- this.error = t('required', this.locale);
4850
- }
4851
- else {
4852
- this.error = '';
4853
- }
5072
+ this.error = requiredError(val, this.required, this.locale);
4854
5073
  this.mrdBlur.emit({ name: this.name, value: val });
4855
5074
  };
4856
5075
  }
4857
5076
  render() {
4858
- const hasError = !!this.error;
4859
- return (index.h(index.Host, { key: 'e9252b251faf98ab190e643b97c13fa32d12ef22' }, index.h("div", { key: '37f4259a111c293f2fe12f321f08c00c25e77feb', class: "mrd-text-field" }, this.label && (index.h("label", { key: 'c59e0346fb71a765ea38629b03c06341567ed210', class: `mrd-text-field__label${this.required ? ' mrd-text-field__label--required' : ''}` }, this.label)), index.h("input", { key: 'dc09953a672472348719f29904d900966d945843', class: `mrd-text-field__input${hasError ? ' mrd-text-field__input--error' : ''}`, type: "text", name: this.name, value: this.value, placeholder: this.placeholder, required: this.required, disabled: this.disabled, onInput: this.handleInput, onBlur: this.handleBlur }), hasError && index.h("span", { key: '037653857a372854a16b28ebf8994b23e3e0d696', class: "mrd-text-field__error" }, this.error))));
5077
+ return (index.h(index.Host, { key: '71de1ae949941820574fc2d45cac6cca8264d8f9' }, index.h("div", { key: 'a63d3dd0811e012ae3d5a9f02c1a2ad1fcc0af86', class: "mrd-text-field" }, index.h(FieldLabel, { key: '1a6db878b634364f47522209344540a9cdc20635', base: "mrd-text-field", label: this.label, required: this.required }), index.h("input", { key: 'b3cd0338f13c5c2c8b744df62d3d02f3bc380aa1', 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 }), index.h(FieldError, { key: '1530066fefbda722df0c37871978995a139fcef0', base: "mrd-text-field", error: this.error }))));
4860
5078
  }
4861
5079
  };
4862
- MrdTextField.style = mrdTextFieldScss();
5080
+ MrdTextField.style = mrdTextFieldCss();
4863
5081
 
4864
- const mrdTextareaFieldScss = () => `.sc-mrd-textarea-field-h{display:block}.mrd-textarea-field.sc-mrd-textarea-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-textarea-field__label.sc-mrd-textarea-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-textarea-field__label--required.sc-mrd-textarea-field::after{content:' *';color:var(--mrd-color-danger)}.mrd-textarea-field__container.sc-mrd-textarea-field{border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);overflow:hidden;background-color:var(--mrd-input-bg);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition)}.mrd-textarea-field__container.sc-mrd-textarea-field:focus-within{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-textarea-field__container--error.sc-mrd-textarea-field{border-color:var(--mrd-border-color-error)}.mrd-textarea-field__container--error.sc-mrd-textarea-field:focus-within{box-shadow:var(--mrd-shadow-focus-error)}.mrd-textarea-field__editor.sc-mrd-textarea-field{min-height:150px;font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base)}.mrd-textarea-field__editor.sc-mrd-textarea-field .ql-toolbar.sc-mrd-textarea-field{border:none;border-bottom:var(--mrd-border-width) solid var(--mrd-border-color);font-family:var(--mrd-font-family)}.mrd-textarea-field__editor.sc-mrd-textarea-field .ql-container.sc-mrd-textarea-field{border:none;font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base)}.mrd-textarea-field__editor.sc-mrd-textarea-field .ql-editor.sc-mrd-textarea-field{min-height:120px;padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x)}.mrd-textarea-field__editor.sc-mrd-textarea-field .ql-editor.ql-blank.sc-mrd-textarea-field::before{color:var(--mrd-input-placeholder-color);font-style:normal}.mrd-textarea-field__error.sc-mrd-textarea-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}`;
5082
+ const mrdTextareaFieldCss = () => `.sc-mrd-textarea-field-h{display:block}.mrd-textarea-field.sc-mrd-textarea-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-textarea-field__label.sc-mrd-textarea-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-textarea-field__label--required.sc-mrd-textarea-field::after{content:" *";color:var(--mrd-color-danger)}.mrd-textarea-field__error.sc-mrd-textarea-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}.mrd-textarea-field__container.sc-mrd-textarea-field{border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);overflow:hidden;background-color:var(--mrd-input-bg);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition)}.mrd-textarea-field__container.sc-mrd-textarea-field:focus-within{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-textarea-field__container--error.sc-mrd-textarea-field{border-color:var(--mrd-border-color-error)}.mrd-textarea-field__container--error.sc-mrd-textarea-field:focus-within{box-shadow:var(--mrd-shadow-focus-error)}.mrd-textarea-field__editor.sc-mrd-textarea-field{min-height:150px;font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base)}.mrd-textarea-field__editor.sc-mrd-textarea-field .ql-toolbar.sc-mrd-textarea-field{border:none;border-bottom:var(--mrd-border-width) solid var(--mrd-border-color);font-family:var(--mrd-font-family)}.mrd-textarea-field__editor.sc-mrd-textarea-field .ql-container.sc-mrd-textarea-field{border:none;font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base)}.mrd-textarea-field__editor.sc-mrd-textarea-field .ql-editor.sc-mrd-textarea-field{min-height:120px;padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x)}.mrd-textarea-field__editor.sc-mrd-textarea-field .ql-editor.ql-blank.sc-mrd-textarea-field::before{color:var(--mrd-input-placeholder-color);font-style:normal}`;
4865
5083
 
4866
5084
  const MrdTextareaField = class {
4867
5085
  constructor(hostRef) {
@@ -4914,12 +5132,7 @@ const MrdTextareaField = class {
4914
5132
  var _a, _b;
4915
5133
  if (!range) {
4916
5134
  const html = (_b = (_a = this.editorEl.querySelector('.ql-editor')) === null || _a === void 0 ? void 0 : _a.innerHTML) !== null && _b !== void 0 ? _b : '';
4917
- if (this.required && !validateRequired(html)) {
4918
- this.error = t('required', this.locale);
4919
- }
4920
- else {
4921
- this.error = '';
4922
- }
5135
+ this.error = requiredError(html, this.required, this.locale);
4923
5136
  this.mrdBlur.emit({ name: this.name, value: html });
4924
5137
  }
4925
5138
  });
@@ -4930,13 +5143,13 @@ const MrdTextareaField = class {
4930
5143
  }
4931
5144
  }
4932
5145
  render() {
4933
- return (index.h(index.Host, { key: 'fe7824c81e082c3f2c1cf18c11dde20cb1f40f2c' }, index.h("div", { key: 'adf394a7e146d16bc79006873a209b11d88b2e17', class: "mrd-textarea-field" }, this.label && (index.h("label", { key: '1b0dd2b4cf26c55a0af05c67a3178edc0c9d56c4', class: `mrd-textarea-field__label${this.required ? ' mrd-textarea-field__label--required' : ''}` }, this.label)), index.h("div", { key: '7c8fe88b222af0beed08db492aa9f6d890e0dc5b', class: `mrd-textarea-field__container${this.error ? ' mrd-textarea-field__container--error' : ''}` }, index.h("div", { key: '295968283e94812cb04660117c5bdeaf3647469c', class: "mrd-textarea-field__editor" })), this.error && index.h("span", { key: '5b5ab61053ab0792d4c249de04bd1d13b51469bf', class: "mrd-textarea-field__error" }, this.error))));
5146
+ return (index.h(index.Host, { key: '464c1edde8447043d9352f1b5f9757bba97e9b17' }, index.h("div", { key: '8d06728214f54feeb1063700e5aaf7c439eb5473', class: "mrd-textarea-field" }, index.h(FieldLabel, { key: 'dbf93ecf41bd704706b49f8c455262798fbbe10b', base: "mrd-textarea-field", label: this.label, required: this.required }), index.h("div", { key: '9c39ccfa38ee01b880973966e910ee32aa60b144', class: controlClass('mrd-textarea-field', !!this.error, 'container') }, index.h("div", { key: '0217cd4350c1933018b2b8f489516b6d43a52538', class: "mrd-textarea-field__editor" })), index.h(FieldError, { key: '62d2a5db053ea6e4ec6868440f3ab31e1c05e633', base: "mrd-textarea-field", error: this.error }))));
4934
5147
  }
4935
5148
  get el() { return index.getElement(this); }
4936
5149
  };
4937
- MrdTextareaField.style = mrdTextareaFieldScss();
5150
+ MrdTextareaField.style = mrdTextareaFieldCss();
4938
5151
 
4939
- const mrdTimeFieldScss = () => `.sc-mrd-time-field-h{display:block}.mrd-time-field.sc-mrd-time-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-time-field__label.sc-mrd-time-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-time-field__label--required.sc-mrd-time-field::after{content:' *';color:var(--mrd-color-danger)}.mrd-time-field__input.sc-mrd-time-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box;cursor:pointer}.mrd-time-field__input.sc-mrd-time-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-time-field__input.sc-mrd-time-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-time-field__input--error.sc-mrd-time-field{border-color:var(--mrd-border-color-error)}.mrd-time-field__input--error.sc-mrd-time-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-time-field__error.sc-mrd-time-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}`;
5152
+ const mrdTimeFieldCss = () => `.sc-mrd-time-field-h{display:block}.mrd-time-field.sc-mrd-time-field{display:flex;flex-direction:column;gap:var(--mrd-space-1);width:100%}.mrd-time-field__label.sc-mrd-time-field{display:block;font-family:var(--mrd-font-family);font-size:var(--mrd-label-font-size);font-weight:var(--mrd-label-font-weight);color:var(--mrd-label-color)}.mrd-time-field__label--required.sc-mrd-time-field::after{content:" *";color:var(--mrd-color-danger)}.mrd-time-field__input.sc-mrd-time-field{display:block;width:100%;height:var(--mrd-input-height);padding:var(--mrd-input-padding-y) var(--mrd-input-padding-x);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-input-color);background-color:var(--mrd-input-bg);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius);transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition);outline:none;appearance:none;box-sizing:border-box}.mrd-time-field__input.sc-mrd-time-field::placeholder{color:var(--mrd-input-placeholder-color)}.mrd-time-field__input.sc-mrd-time-field:focus{border-color:var(--mrd-border-color-focus);box-shadow:var(--mrd-shadow-focus)}.mrd-time-field__input.sc-mrd-time-field:disabled{background-color:var(--mrd-input-bg-disabled);cursor:not-allowed;opacity:0.7}.mrd-time-field__input--error.sc-mrd-time-field{border-color:var(--mrd-border-color-error)}.mrd-time-field__input--error.sc-mrd-time-field:focus{box-shadow:var(--mrd-shadow-focus-error)}.mrd-time-field__error.sc-mrd-time-field{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}.mrd-time-field__input.sc-mrd-time-field{cursor:pointer}`;
4940
5153
 
4941
5154
  const MrdTimeField = class {
4942
5155
  constructor(hostRef) {
@@ -4952,12 +5165,7 @@ const MrdTimeField = class {
4952
5165
  this.error = '';
4953
5166
  this.handleChange = (e) => {
4954
5167
  const val = e.target.value;
4955
- if (this.required && !validateRequired(val)) {
4956
- this.error = t('required', this.locale);
4957
- }
4958
- else {
4959
- this.error = '';
4960
- }
5168
+ this.error = requiredError(val, this.required, this.locale);
4961
5169
  this.mrdChange.emit({ name: this.name, value: val });
4962
5170
  };
4963
5171
  this.handleBlur = (e) => {
@@ -4966,11 +5174,10 @@ const MrdTimeField = class {
4966
5174
  };
4967
5175
  }
4968
5176
  render() {
4969
- const hasError = !!this.error;
4970
- return (index.h(index.Host, { key: '579219a478e31325b5a676465807c1d936724a2b' }, index.h("div", { key: '51b25f6e083a29989505c0ad79edbcd3b0060736', class: "mrd-time-field" }, this.label && (index.h("label", { key: '67d98bebb8803deea2d2a4a63f36706789ccd8c7', class: `mrd-time-field__label${this.required ? ' mrd-time-field__label--required' : ''}` }, this.label)), index.h("input", { key: '734741e0db1bdd5886fef37bba3b2f8d7200a0ab', class: `mrd-time-field__input${hasError ? ' mrd-time-field__input--error' : ''}`, type: "time", name: this.name, value: this.value, required: this.required, disabled: this.disabled, onChange: this.handleChange, onBlur: this.handleBlur }), hasError && index.h("span", { key: '0dbd168d14966dc56a77c97cd8fd8f9b208a4bf5', class: "mrd-time-field__error" }, this.error))));
5177
+ return (index.h(index.Host, { key: 'fc30bdeb7c8d37bebc67a768f48013602879fb3d' }, index.h("div", { key: '52f899a889376773c1948f0c116670684db25cf4', class: "mrd-time-field" }, index.h(FieldLabel, { key: '3aba58f122fa4bb9f0ba4ad0b56fc3b29f03d4a3', base: "mrd-time-field", label: this.label, required: this.required }), index.h("input", { key: 'e39718394a195eafaf47aa2e62d560341bb0daed', 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 }), index.h(FieldError, { key: '07ad4ccbc5188e129d8bd3085e856839ec6a81c9', base: "mrd-time-field", error: this.error }))));
4971
5178
  }
4972
5179
  };
4973
- MrdTimeField.style = mrdTimeFieldScss();
5180
+ MrdTimeField.style = mrdTimeFieldCss();
4974
5181
 
4975
5182
  exports.mrd_boolean_field = MrdBooleanField;
4976
5183
  exports.mrd_currency_field = MrdCurrencyField;