@mmlogic/components 0.5.13 → 0.5.15

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 (74) hide show
  1. package/dist/cjs/{cell-renderer-BBebjBVz.js → cell-renderer-CLVKTVVQ.js} +113 -1
  2. package/dist/cjs/{client-layout-CqVuJumR.js → client-layout-Eg2VwW-7.js} +2 -0
  3. package/dist/cjs/index.cjs.js +2 -1
  4. package/dist/cjs/loader.cjs.js +1 -1
  5. package/dist/cjs/mosterdcomponents.cjs.js +1 -1
  6. package/dist/cjs/{mrd-boolean-field_25.cjs.entry.js → mrd-boolean-field_28.cjs.entry.js} +1163 -356
  7. package/dist/cjs/mrd-merge-view.cjs.entry.js +4 -4
  8. package/dist/collection/collection-manifest.json +3 -0
  9. package/dist/collection/components/fields/mrd-textarea-field/mrd-textarea-field.js +47 -2
  10. package/dist/collection/components/form/mrd-form/mrd-form.css +29 -0
  11. package/dist/collection/components/form/mrd-form/mrd-form.js +44 -8
  12. package/dist/collection/components/layout/mrd-layout-section/mrd-layout-section.js +126 -13
  13. package/dist/collection/components/memo/mrd-memo-container/mrd-memo-container.css +204 -0
  14. package/dist/collection/components/memo/mrd-memo-container/mrd-memo-container.js +694 -0
  15. package/dist/collection/components/memo/mrd-memo-list/mrd-memo-list.css +150 -0
  16. package/dist/collection/components/memo/mrd-memo-list/mrd-memo-list.js +511 -0
  17. package/dist/collection/components/memo/mrd-memo-view/mrd-memo-view.css +108 -0
  18. package/dist/collection/components/memo/mrd-memo-view/mrd-memo-view.js +204 -0
  19. package/dist/collection/components/merge/mrd-merge-view/mrd-merge-view.js +2 -2
  20. package/dist/collection/components/table/mrd-table/mrd-table.css +36 -0
  21. package/dist/collection/components/table/mrd-table/mrd-table.js +146 -31
  22. package/dist/collection/components/table/mrd-table/table-parts.js +6 -2
  23. package/dist/collection/components/table/mrd-table/table-query.js +6 -0
  24. package/dist/collection/dev/app.js +17 -0
  25. package/dist/collection/types/client-layout.js +1 -0
  26. package/dist/collection/utils/i18n.js +112 -0
  27. package/dist/collection/utils/query-params.js +9 -0
  28. package/dist/components/client-layout.js +1 -1
  29. package/dist/components/i18n.js +1 -1
  30. package/dist/components/index.js +1 -1
  31. package/dist/components/mrd-form.js +1 -1
  32. package/dist/components/mrd-layout-section.js +1 -1
  33. package/dist/components/mrd-memo-container.d.ts +11 -0
  34. package/dist/components/mrd-memo-container.js +1 -0
  35. package/dist/components/mrd-memo-container2.js +1 -0
  36. package/dist/components/mrd-memo-list.d.ts +11 -0
  37. package/dist/components/mrd-memo-list.js +1 -0
  38. package/dist/components/mrd-memo-list2.js +1 -0
  39. package/dist/components/mrd-memo-view.d.ts +11 -0
  40. package/dist/components/mrd-memo-view.js +1 -0
  41. package/dist/components/mrd-memo-view2.js +1 -0
  42. package/dist/components/mrd-merge-view.js +1 -1
  43. package/dist/components/mrd-table2.js +1 -1
  44. package/dist/components/mrd-textarea-field2.js +1 -1
  45. package/dist/components/query-params.js +1 -1
  46. package/dist/components/table-query.js +1 -0
  47. package/dist/esm/{cell-renderer-CC8-MtvQ.js → cell-renderer-4NKEzZWw.js} +113 -1
  48. package/dist/esm/{client-layout-Bc42CfJB.js → client-layout-BJkVeSq6.js} +2 -1
  49. package/dist/esm/index.js +1 -1
  50. package/dist/esm/loader.js +1 -1
  51. package/dist/esm/mosterdcomponents.js +1 -1
  52. package/dist/esm/{mrd-boolean-field_25.entry.js → mrd-boolean-field_28.entry.js} +1161 -357
  53. package/dist/esm/mrd-merge-view.entry.js +4 -4
  54. package/dist/mosterdcomponents/index.esm.js +1 -1
  55. package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
  56. package/dist/mosterdcomponents/{p-Bc42CfJB.js → p-BJkVeSq6.js} +1 -1
  57. package/dist/mosterdcomponents/p-BMx6VAJ6.js +1 -0
  58. package/dist/mosterdcomponents/p-d64ba1f2.entry.js +3 -0
  59. package/dist/mosterdcomponents/{p-a7e8f6a3.entry.js → p-e68dfbb0.entry.js} +1 -1
  60. package/dist/types/components/fields/mrd-textarea-field/mrd-textarea-field.d.ts +10 -0
  61. package/dist/types/components/form/mrd-form/mrd-form.d.ts +6 -0
  62. package/dist/types/components/layout/mrd-layout-section/mrd-layout-section.d.ts +20 -1
  63. package/dist/types/components/memo/mrd-memo-container/mrd-memo-container.d.ts +152 -0
  64. package/dist/types/components/memo/mrd-memo-list/mrd-memo-list.d.ts +79 -0
  65. package/dist/types/components/memo/mrd-memo-view/mrd-memo-view.d.ts +33 -0
  66. package/dist/types/components/table/mrd-table/mrd-table.d.ts +48 -1
  67. package/dist/types/components/table/mrd-table/table-parts.d.ts +15 -0
  68. package/dist/types/components/table/mrd-table/table-query.d.ts +6 -0
  69. package/dist/types/components.d.ts +528 -1
  70. package/dist/types/types/client-layout.d.ts +1 -0
  71. package/dist/types/utils/query-params.d.ts +16 -0
  72. package/package.json +1 -1
  73. package/dist/mosterdcomponents/p-07b148b2.entry.js +0 -3
  74. package/dist/mosterdcomponents/p-D5ZPfX3-.js +0 -1
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var index = require('./index-DVbdkYO3.js');
4
- var cellRenderer = require('./cell-renderer-BBebjBVz.js');
5
- var clientLayout = require('./client-layout-CqVuJumR.js');
4
+ var cellRenderer = require('./cell-renderer-CLVKTVVQ.js');
5
+ var clientLayout = require('./client-layout-Eg2VwW-7.js');
6
6
 
7
7
  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)}`;
8
8
 
@@ -522,6 +522,15 @@ function buildListPath(opts) {
522
522
  }
523
523
  return `/${(_c = opts.dataClass) !== null && _c !== void 0 ? _c : ''}`;
524
524
  }
525
+ /** The `mrdAction` detail for a toolbar "create" action: `parentPath` locates the
526
+ * RELATED_VIEW's parent (`/{fromClass}/{parentId}`) so the host can route to
527
+ * `.../{parentPath}/{dataClass}/new`; `null` for a top-level VIEW. Shared by
528
+ * mrd-table and mrd-memo-container so both toolbars build an identical payload. */
529
+ function buildCreateActionDetail(opts) {
530
+ var _a, _b;
531
+ const parentPath = opts.isRelatedView ? `/${(_a = opts.fromClass) !== null && _a !== void 0 ? _a : ''}/${opts.parentId}` : null;
532
+ return Object.assign({ action: 'create', dataClass: (_b = opts.dataClass) !== null && _b !== void 0 ? _b : '', parentPath }, (opts.basicType ? { basicType: opts.basicType } : {}));
533
+ }
525
534
 
526
535
  /**
527
536
  * Tree model and pure tree logic for mrd-document-list.
@@ -4444,13 +4453,14 @@ const MrdFileField = class {
4444
4453
  };
4445
4454
  MrdFileField.style = mrdFileFieldCss();
4446
4455
 
4447
- 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)}`;
4456
+ 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)}.mrd-form__delete.sc-mrd-form{display:inline-flex;align-items:center;justify-content:center;height:var(--mrd-input-height);padding:0 var(--mrd-space-6);margin-right:auto;background-color:transparent;color:var(--mrd-color-danger);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-color-danger);border-radius:var(--mrd-border-radius);cursor:pointer;transition:background-color var(--mrd-transition), color var(--mrd-transition)}.mrd-form__delete.sc-mrd-form:hover{background-color:var(--mrd-color-danger-light);color:var(--mrd-color-danger-dark)}.mrd-form__delete.sc-mrd-form:focus{outline:none;box-shadow:0 0 0 3px var(--mrd-color-danger-light)}.mrd-form__delete.sc-mrd-form:active{background-color:var(--mrd-color-danger-light);border-color:var(--mrd-color-danger-dark)}`;
4448
4457
 
4449
4458
  const MrdForm = class {
4450
4459
  constructor(hostRef) {
4451
4460
  index.registerInstance(this, hostRef);
4452
4461
  this.mrdSubmit = index.createEvent(this, "mrdSubmit");
4453
4462
  this.mrdCancel = index.createEvent(this, "mrdCancel");
4463
+ this.mrdDelete = index.createEvent(this, "mrdDelete");
4454
4464
  this.mrdSearch = index.createEvent(this, "mrdSearch");
4455
4465
  this.mrdFetchAll = index.createEvent(this, "mrdFetchAll");
4456
4466
  this.mrdUpload = index.createEvent(this, "mrdUpload");
@@ -4477,6 +4487,11 @@ const MrdForm = class {
4477
4487
  this.referenceClass = '';
4478
4488
  /** When true, a cancel button is shown next to the submit button. */
4479
4489
  this.showCancel = false;
4490
+ /** When true, a delete button is shown next to the submit button (edit mode only —
4491
+ * the host decides when a delete affordance makes sense, e.g. only for an existing
4492
+ * record). Deletion itself (confirmation, the actual API call) is entirely the
4493
+ * host's responsibility; mrd-form only emits the request via mrdDelete. */
4494
+ this.showDelete = false;
4480
4495
  /**
4481
4496
  * The currently logged-in user, resolved by the host via /accounts/me.
4482
4497
  * Used to pre-fill RELATION fields whose defaultValue is "@me".
@@ -4764,15 +4779,11 @@ const MrdForm = class {
4764
4779
  normalizeRelationValue(value) {
4765
4780
  if (value == null || value === '')
4766
4781
  return null;
4767
- if (typeof value === 'string')
4768
- return value || null;
4769
4782
  if (Array.isArray(value)) {
4770
- return value.map(v => typeof v === 'object' && v !== null && 'id' in v ? v.id : String(v));
4771
- }
4772
- if (typeof value === 'object' && 'id' in value) {
4773
- return value.id || null;
4783
+ const hrefs = value.map(v => this.getHref(v)).filter(v => v !== '');
4784
+ return hrefs.length ? hrefs : null;
4774
4785
  }
4775
- return null;
4786
+ return this.getHref(value) || null;
4776
4787
  }
4777
4788
  deepEqual(a, b) {
4778
4789
  if (a === b)
@@ -4845,7 +4856,7 @@ const MrdForm = class {
4845
4856
  return index.h(index.Host, null);
4846
4857
  }
4847
4858
  const dir = this.locale.startsWith('ar') ? 'rtl' : 'ltr';
4848
- return (index.h(index.Host, null, index.h("form", { class: "mrd-form", dir: dir, onSubmit: this.handleSubmit, noValidate: true }, this.layout.title && index.h("h2", { class: "mrd-form__title" }, this.layout.title), index.h("div", { class: "mrd-form__body" }, this.renderItems(this.layout.items)), index.h("div", { class: "mrd-form__footer" }, index.h("button", { type: "submit", class: "mrd-form__submit" }, cellRenderer.t('submit', this.locale)), this.showCancel && (index.h("button", { type: "button", class: "mrd-form__cancel", onClick: () => this.mrdCancel.emit() }, cellRenderer.t('cancel', this.locale)))))));
4859
+ return (index.h(index.Host, null, index.h("form", { class: "mrd-form", dir: dir, onSubmit: this.handleSubmit, noValidate: true }, this.layout.title && index.h("h2", { class: "mrd-form__title" }, this.layout.title), index.h("div", { class: "mrd-form__body" }, this.renderItems(this.layout.items)), index.h("div", { class: "mrd-form__footer" }, this.showDelete && (index.h("button", { type: "button", class: "mrd-form__delete", onClick: () => this.mrdDelete.emit() }, cellRenderer.t('delete', this.locale))), index.h("button", { type: "submit", class: "mrd-form__submit" }, cellRenderer.t('submit', this.locale)), this.showCancel && (index.h("button", { type: "button", class: "mrd-form__cancel", onClick: () => this.mrdCancel.emit() }, cellRenderer.t('cancel', this.locale)))))));
4849
4860
  }
4850
4861
  static get watchers() { return {
4851
4862
  "values": [{
@@ -5339,6 +5350,7 @@ const MrdLayoutSection = class {
5339
5350
  this.mrdLoadViewAggregations = index.createEvent(this, "mrdLoadViewAggregations");
5340
5351
  this.mrdLoadViewDistinct = index.createEvent(this, "mrdLoadViewDistinct");
5341
5352
  this.mrdUpdateObject = index.createEvent(this, "mrdUpdateObject");
5353
+ this.mrdDeleteObject = index.createEvent(this, "mrdDeleteObject");
5342
5354
  this.mrdViewUpload = index.createEvent(this, "mrdViewUpload");
5343
5355
  this.mrdCreateObject = index.createEvent(this, "mrdCreateObject");
5344
5356
  /** Items from one layout entry in ClientDashboardMetadata.layouts[]. */
@@ -5357,6 +5369,11 @@ const MrdLayoutSection = class {
5357
5369
  * create ("+") action and the documents view's New folder / Upload are disabled
5358
5370
  * with a tooltip explaining why, so it's clear at a glance the user can't mutate data. */
5359
5371
  this.readOnly = false;
5372
+ /** The active account's linked person record (userProfile.links.person), if any.
5373
+ * Threaded to mrd-memo-container so a top-level memo VIEW (no parent record to
5374
+ * attach a new memo to) can still offer "New memo" by falling back to the
5375
+ * account's own record as the container. */
5376
+ this.me = null;
5360
5377
  this.searchQueryMap = {};
5361
5378
  this.searchResultsMap = {};
5362
5379
  this.imagePreviewUrl = null;
@@ -5410,6 +5427,14 @@ const MrdLayoutSection = class {
5410
5427
  await table.init();
5411
5428
  }
5412
5429
  }
5430
+ // mrd-memo-container's card mode has no <mrd-table> — mrd-memo-list needs the
5431
+ // same init() call to request its first page.
5432
+ const memoLists = this.el.querySelectorAll('mrd-memo-list[data-view]');
5433
+ for (const list of Array.from(memoLists)) {
5434
+ if (typeof list.init === 'function') {
5435
+ await list.init();
5436
+ }
5437
+ }
5413
5438
  }
5414
5439
  emitLoadImages() {
5415
5440
  for (const item of flattenItems(this.items)) {
@@ -5443,12 +5468,18 @@ const MrdLayoutSection = class {
5443
5468
  return;
5444
5469
  }
5445
5470
  const table = this.el.querySelector(`mrd-table[data-view="${name}"]`);
5446
- if (!table)
5471
+ if (table) {
5472
+ if (totalElements !== undefined) {
5473
+ table.totalElements = totalElements;
5474
+ }
5475
+ await table.setPage(page, rows, hasNext);
5447
5476
  return;
5448
- if (totalElements !== undefined) {
5449
- table.totalElements = totalElements;
5450
5477
  }
5451
- await table.setPage(page, rows, hasNext);
5478
+ // Cards mode: mrd-memo-container mounts mrd-memo-list instead of mrd-table.
5479
+ const memoList = this.el.querySelector(`mrd-memo-list[data-view="${name}"]`);
5480
+ if (memoList) {
5481
+ await memoList.setPage(page, rows, hasNext);
5482
+ }
5452
5483
  }
5453
5484
  /** Inject aggregation totals into an embedded mrd-table for a VIEW or RELATED_VIEW item. */
5454
5485
  async setViewAggregations(name, data) {
@@ -5471,11 +5502,18 @@ const MrdLayoutSection = class {
5471
5502
  await list.setFileReference(uri);
5472
5503
  }
5473
5504
  /** Inject the created document's href after a file-drop create, so the
5474
- * optimistic row becomes navigable (see mrdCreateObject). */
5505
+ * optimistic row becomes navigable (see mrdCreateObject). For a memo
5506
+ * quick-create there is no optimistic row to resolve — simply reload the
5507
+ * container's current body so the new memo shows up. */
5475
5508
  async setViewCreatedObject(name, href) {
5476
5509
  const list = this.el.querySelector(`mrd-document-list[data-doclist="${name}"]`);
5477
- if (list === null || list === void 0 ? void 0 : list.setCreatedHref)
5510
+ if (list === null || list === void 0 ? void 0 : list.setCreatedHref) {
5478
5511
  await list.setCreatedHref(href);
5512
+ return;
5513
+ }
5514
+ const memoContainer = this.el.querySelector(`mrd-memo-container[data-view="${name}"]`);
5515
+ if (memoContainer === null || memoContainer === void 0 ? void 0 : memoContainer.refresh)
5516
+ await memoContainer.refresh();
5479
5517
  }
5480
5518
  /** Provide a resolved URL for an IMAGE field. Shows as thumbnail; clicking opens the lightbox. */
5481
5519
  async setImagePreview(fieldName, url) {
@@ -5537,7 +5575,7 @@ const MrdLayoutSection = class {
5537
5575
  return (index.h("div", { class: "mrd-layout-section__search", key: `search-${dataClass}` }, index.h("div", { class: "mrd-layout-section__search-wrap" }, index.h("svg", { class: "mrd-layout-section__search-icon", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", "aria-hidden": "true" }, index.h("path", { "fill-rule": "evenodd", d: "M9 3.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM2 9a7 7 0 1112.452 4.391l3.328 3.329a.75.75 0 11-1.06 1.06l-3.329-3.328A7 7 0 012 9z", "clip-rule": "evenodd" })), index.h("input", { class: "mrd-layout-section__search-input", type: "text", value: query, placeholder: (_c = item.label) !== null && _c !== void 0 ? _c : '', onInput: e => this.handleSearchInput(dataClass, e.target.value) })), results.length > 0 && (index.h("ul", { class: "mrd-layout-section__search-results" }, results.map(r => (index.h("li", { key: r.id, class: "mrd-layout-section__search-result" }, index.h("button", { class: "mrd-layout-section__search-result-btn", onClick: () => this.mrdNavigate.emit({ href: r.id, label: r.label }) }, index.h("span", { class: "mrd-layout-section__search-result-label" }, r.label), r.description && index.h("span", { class: "mrd-layout-section__search-result-desc" }, r.description)))))))));
5538
5576
  }
5539
5577
  renderRelatedView(item) {
5540
- var _a, _b, _c, _d, _e, _f, _g, _h;
5578
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
5541
5579
  const key = viewKeyFor(item);
5542
5580
  if (!key)
5543
5581
  return null;
@@ -5550,13 +5588,12 @@ const MrdLayoutSection = class {
5550
5588
  // The API publishes `archetypes` on the VIEW/RELATED_VIEW item itself
5551
5589
  // (sibling of `view`), not inside `view`.
5552
5590
  const docArchetype = clientLayout.resolveArchetype((_g = item.archetypes) !== null && _g !== void 0 ? _g : (_h = item.view) === null || _h === void 0 ? void 0 : _h.archetypes, clientLayout.ARCHETYPE_DOCUMENT);
5591
+ const memoArchetype = !docArchetype ? clientLayout.resolveArchetype((_j = item.archetypes) !== null && _j !== void 0 ? _j : (_k = item.view) === null || _k === void 0 ? void 0 : _k.archetypes, clientLayout.ARCHETYPE_MEMO) : undefined;
5553
5592
  // Canonical parent href for single-container seeding: use the RELATED_VIEW's
5554
5593
  // fromClass (base class) rather than the route class, so polymorphic subtypes
5555
5594
  // resolve to the same container the documents actually reference.
5556
5595
  const containerHref = buildContainerHref(item, selfHref, parentId);
5557
- 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
5558
- ? this.renderDocumentContainer(item, key, parentId, docArchetype, containerHref)
5559
- : this.renderTable(item, key, parentId)));
5596
+ 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 && this.renderDocumentContainer(item, key, parentId, docArchetype, containerHref), memoArchetype && this.renderMemoContainer(item, key, parentId, memoArchetype, containerHref), !docArchetype && !memoArchetype && this.renderTable(item, key, parentId)));
5560
5597
  }
5561
5598
  /** Document collection view: owns the view-switch + collection actions and
5562
5599
  * swaps between the folder tree and the flat table. Events are re-emitted to
@@ -5594,6 +5631,33 @@ const MrdLayoutSection = class {
5594
5631
  this.mrdCreateObject.emit(Object.assign({ name: key }, e.detail));
5595
5632
  } }));
5596
5633
  }
5634
+ /** Memo collection view: owns the view-switch + "New memo" and swaps between
5635
+ * the card list and the flat table, mirroring renderDocumentContainer(). */
5636
+ renderMemoContainer(item, key, parentId, archetype, containerHref) {
5637
+ var _a, _b, _c, _d;
5638
+ const labelsListItems = (_d = (_c = (_b = (_a = item.view) === null || _a === void 0 ? void 0 : _a.values) === null || _b === void 0 ? void 0 : _b.find(v => { var _a; return v.name === ((_a = archetype.slots) === null || _a === void 0 ? void 0 : _a.labels); })) === null || _c === void 0 ? void 0 : _c.listItems) !== null && _d !== void 0 ? _d : null;
5639
+ return (index.h("mrd-memo-container", { "data-view": key, item: item, archetype: archetype, parentId: parentId, containerHref: containerHref, viewKey: key, locale: this.locale, readOnly: this.readOnly, me: this.me, labelsListItems: labelsListItems, onMrdLoadPage: (e) => {
5640
+ e.stopPropagation();
5641
+ this.mrdLoadViewPage.emit(Object.assign({ name: key }, e.detail));
5642
+ }, onMrdLoadAggregations: (e) => {
5643
+ var _a;
5644
+ e.stopPropagation();
5645
+ this.mrdLoadViewAggregations.emit(Object.assign({ name: key, dataClass: (_a = item.dataClass) !== null && _a !== void 0 ? _a : key }, e.detail));
5646
+ }, onMrdAction: (e) => {
5647
+ var _a;
5648
+ e.stopPropagation();
5649
+ this.mrdViewAction.emit(Object.assign({ name: key, dataClass: (_a = item.dataClass) !== null && _a !== void 0 ? _a : key }, e.detail));
5650
+ }, onMrdCreateObject: (e) => {
5651
+ e.stopPropagation();
5652
+ this.mrdCreateObject.emit(Object.assign({ name: key }, e.detail));
5653
+ }, onMrdUpdateObject: (e) => {
5654
+ e.stopPropagation();
5655
+ this.mrdUpdateObject.emit(e.detail);
5656
+ }, onMrdDeleteObject: (e) => {
5657
+ e.stopPropagation();
5658
+ this.mrdDeleteObject.emit(e.detail);
5659
+ } }));
5660
+ }
5597
5661
  renderTable(item, key, parentId) {
5598
5662
  return (index.h("mrd-table", { "data-view": key, item: item, parentId: parentId, locale: this.locale, readOnly: this.readOnly, onMrdLoadPage: (e) => this.handleViewLoadPage(e, key), onMrdLoadAggregations: (e) => {
5599
5663
  var _a;
@@ -5695,11 +5759,24 @@ const MrdLayoutSection = class {
5695
5759
  ...this.relatedItems().map(it => this.renderItem(it)),
5696
5760
  ];
5697
5761
  }
5762
+ /** Single-memo view: the record's own type carries commons.memo. Renders a
5763
+ * recognisable memo (title/body prominent, author/date subtle) instead of
5764
+ * generic fields, keeping any related views/searches below it. */
5765
+ renderMemoObject(archetype) {
5766
+ var _a, _b;
5767
+ const labelsListItems = (_b = (_a = this.items.find(it => { var _a; return it.name === ((_a = archetype.slots) === null || _a === void 0 ? void 0 : _a.labels); })) === null || _a === void 0 ? void 0 : _a.listItems) !== null && _b !== void 0 ? _b : null;
5768
+ return [
5769
+ index.h("mrd-memo-view", { archetype: archetype, data: this.data, locale: this.locale, labelsListItems: labelsListItems, onMrdNavigate: (e) => { e.stopPropagation(); this.mrdNavigate.emit(e.detail); } }),
5770
+ ...this.relatedItems().map(it => this.renderItem(it)),
5771
+ ];
5772
+ }
5698
5773
  render() {
5699
5774
  const docArchetype = clientLayout.resolveArchetype(this.archetypes, clientLayout.ARCHETYPE_DOCUMENT);
5700
5775
  const invoiceArchetype = !docArchetype ? clientLayout.resolveArchetype(this.archetypes, clientLayout.ARCHETYPE_INVOICE) : undefined;
5701
5776
  const emailArchetype = !docArchetype && !invoiceArchetype ? clientLayout.resolveArchetype(this.archetypes, clientLayout.ARCHETYPE_EMAIL) : undefined;
5702
- return (index.h(index.Host, { key: '07b1d61b170a5ae971ba54eaf775e1787dea1642' }, index.h("div", { key: 'd146e0542b1de11bd130eb3d36d54e4faf055309', class: "mrd-layout-section" }, docArchetype && this.renderDocumentObject(docArchetype), invoiceArchetype && this.renderInvoiceObject(invoiceArchetype), emailArchetype && this.renderEmailObject(emailArchetype), !docArchetype && !invoiceArchetype && !emailArchetype && this.items.map(item => this.renderItem(item))), this.renderImageModal()));
5777
+ const memoArchetype = !docArchetype && !invoiceArchetype && !emailArchetype ? clientLayout.resolveArchetype(this.archetypes, clientLayout.ARCHETYPE_MEMO) : undefined;
5778
+ const anyArchetype = docArchetype || invoiceArchetype || emailArchetype || memoArchetype;
5779
+ return (index.h(index.Host, { key: '730654d745992b9607f15fcaf2bb54a725429e4d' }, index.h("div", { key: '72a2e7bb767992aa6f206a10f8b2a3a572e86115', class: "mrd-layout-section" }, docArchetype && this.renderDocumentObject(docArchetype), invoiceArchetype && this.renderInvoiceObject(invoiceArchetype), emailArchetype && this.renderEmailObject(emailArchetype), memoArchetype && this.renderMemoObject(memoArchetype), !anyArchetype && this.items.map(item => this.renderItem(item))), this.renderImageModal()));
5703
5780
  }
5704
5781
  get el() { return index.getElement(this); }
5705
5782
  static get watchers() { return {
@@ -5823,153 +5900,916 @@ const MrdLongtextField = class {
5823
5900
  };
5824
5901
  MrdLongtextField.style = mrdLongtextFieldCss();
5825
5902
 
5826
- 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)}`;
5903
+ const mrdMemoContainerCss = () => `.sc-mrd-memo-container-h{display:block}.mrd-memo-container__toolbar.sc-mrd-memo-container{display:flex;align-items:center;justify-content:flex-end;gap:var(--mrd-space-2);padding:var(--mrd-space-2) 0;border-bottom:1px solid var(--mrd-color-neutral-100)}.mrd-memo-container__action.sc-mrd-memo-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-memo-container__action.sc-mrd-memo-container svg.sc-mrd-memo-container{width:1rem;height:1rem}.mrd-memo-container__action.sc-mrd-memo-container:hover:not(:disabled){background:var(--mrd-color-neutral-50);border-color:var(--mrd-color-neutral-300)}.mrd-memo-container__action.sc-mrd-memo-container:disabled{opacity:0.5;cursor:not-allowed}.mrd-memo-container__seg.sc-mrd-memo-container{display:inline-flex;gap:2px;padding:2px;background:var(--mrd-color-neutral-100);border-radius:var(--mrd-border-radius)}.mrd-memo-container__seg-btn.sc-mrd-memo-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-memo-container__seg-btn.sc-mrd-memo-container:hover{color:var(--mrd-color-neutral-800)}.mrd-memo-container__seg-btn[aria-pressed=true].sc-mrd-memo-container{background:var(--mrd-color-white);color:var(--mrd-color-primary-dark);box-shadow:var(--mrd-shadow-sm)}.mrd-memo-container__seg-btn.sc-mrd-memo-container svg.sc-mrd-memo-container{width:1rem;height:1rem}.mrd-memo-container__body.sc-mrd-memo-container{padding-top:var(--mrd-space-3)}.mrd-memo-container__modal-backdrop.sc-mrd-memo-container{position:fixed;inset:0;background:rgba(0, 0, 0, 0.6);z-index:300;display:flex;align-items:center;justify-content:center;padding:var(--mrd-space-4)}.mrd-memo-container__modal.sc-mrd-memo-container{width:100%;max-width:960px;max-height:90vh;overflow-y:auto;display:flex;flex-direction:column;gap:var(--mrd-space-4);background:var(--mrd-color-white);border-radius:var(--mrd-border-radius-md);padding:var(--mrd-space-5);box-shadow:var(--mrd-shadow-lg)}.mrd-memo-container__modal-title.sc-mrd-memo-container{font-size:var(--mrd-font-size-lg);font-weight:var(--mrd-font-weight-bold);color:var(--mrd-color-neutral-900);margin:0}.mrd-memo-container__modal-field.sc-mrd-memo-container{display:flex;flex-direction:column;gap:var(--mrd-space-1)}.mrd-memo-container__modal-error.sc-mrd-memo-container{font-family:var(--mrd-font-family);font-size:var(--mrd-error-font-size);color:var(--mrd-error-color)}.mrd-memo-container__modal-warning.sc-mrd-memo-container{margin:0;font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-base);color:var(--mrd-color-neutral-600)}.mrd-memo-container__modal-actions.sc-mrd-memo-container{display:flex;justify-content:flex-end;gap:var(--mrd-space-3);margin-top:var(--mrd-space-2);padding-top:var(--mrd-space-4);border-top:var(--mrd-border-width) solid var(--mrd-border-color)}.mrd-memo-container__modal-delete.sc-mrd-memo-container{display:inline-flex;align-items:center;justify-content:center;height:var(--mrd-input-height);padding:0 var(--mrd-space-6);margin-right:auto;background-color:transparent;color:var(--mrd-color-danger);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-color-danger);border-radius:var(--mrd-border-radius);cursor:pointer;transition:background-color var(--mrd-transition), color var(--mrd-transition)}.mrd-memo-container__modal-delete.sc-mrd-memo-container:hover{background-color:var(--mrd-color-danger-light);color:var(--mrd-color-danger-dark)}.mrd-memo-container__modal-delete-confirm.sc-mrd-memo-container{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-danger);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-memo-container__modal-delete-confirm.sc-mrd-memo-container:hover{background-color:var(--mrd-color-danger-dark)}.mrd-memo-container__modal-cancel.sc-mrd-memo-container{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-memo-container__modal-cancel.sc-mrd-memo-container:hover{background-color:var(--mrd-color-neutral-100);color:var(--mrd-color-neutral-800)}.mrd-memo-container__modal-submit.sc-mrd-memo-container{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-memo-container__modal-submit.sc-mrd-memo-container:hover{background-color:var(--mrd-color-primary-hover)}`;
5827
5904
 
5828
- const MrdNumberField = class {
5905
+ const MrdMemoContainer = class {
5829
5906
  constructor(hostRef) {
5830
5907
  index.registerInstance(this, hostRef);
5831
- this.mrdChange = index.createEvent(this, "mrdChange");
5832
- this.mrdBlur = index.createEvent(this, "mrdBlur");
5833
- this.name = '';
5834
- this.label = '';
5835
- this.value = null;
5836
- this.placeholder = '';
5837
- this.required = false;
5838
- this.disabled = false;
5908
+ this.mrdLoadPage = index.createEvent(this, "mrdLoadPage");
5909
+ this.mrdLoadAggregations = index.createEvent(this, "mrdLoadAggregations");
5910
+ this.mrdAction = index.createEvent(this, "mrdAction");
5911
+ this.mrdCreateObject = index.createEvent(this, "mrdCreateObject");
5912
+ this.mrdUpdateObject = index.createEvent(this, "mrdUpdateObject");
5913
+ this.mrdDeleteObject = index.createEvent(this, "mrdDeleteObject");
5914
+ /** The VIEW or RELATED_VIEW layout item (dataClass, fromClass, view config). */
5915
+ this.item = null;
5916
+ /** Parent record id — required for RELATED_VIEW path building. */
5917
+ this.parentId = '';
5918
+ /** Canonical parent href — set when this is a RELATED_VIEW embedded under a
5919
+ * parent record, which already gives a new memo something to attach to. */
5920
+ this.containerHref = '';
5921
+ /** Lookup key used for the embedded `data-view` attribute. */
5922
+ this.viewKey = '';
5839
5923
  this.locale = navigator.language;
5840
- this.dataType = clientLayout.ClientLayoutItemFieldDataType.INTEGER;
5841
- this.decimalPrecision = 2;
5842
- this.displayValue = '';
5843
- this.error = '';
5844
- /** While focused the user owns the text; prop updates must not overwrite it. */
5845
- this.focused = false;
5846
- this.handleInput = (e) => {
5847
- this.displayValue = e.target.value;
5924
+ /** listItems of the FIELD bound to the `labels` slot; forwarded to whichever
5925
+ * body is mounted and used to render the dialog's label checkboxes. */
5926
+ this.labelsListItems = null;
5927
+ /** When true, this dashboard is read-only: "New memo" is disabled with a
5928
+ * tooltip, cards/rows are not clickable, and the embedded table's own
5929
+ * create action is disabled too. */
5930
+ this.readOnly = false;
5931
+ /** The active account's linked person record (userProfile.links.person), if any.
5932
+ * Used both to gate "New memo" (see effectiveContainerHref) and, on submit, to
5933
+ * fill the author slot. */
5934
+ this.me = null;
5935
+ /** Active body: card list or flat table. */
5936
+ this.mode = 'cards';
5937
+ this.dialogOpen = false;
5938
+ /** Href of the memo being edited; null while creating. */
5939
+ this.editingHref = null;
5940
+ this.dialogBody = '';
5941
+ this.dialogTitle = '';
5942
+ this.dialogLabels = [];
5943
+ this.dialogImportant = false;
5944
+ this.dialogTouched = false;
5945
+ /** True while the dialog shows the delete confirmation step in place of the
5946
+ * form fields — mirrors mrd-merge-view's MergeConfirmStep (same panel,
5947
+ * swapped content) rather than stacking a second modal. */
5948
+ this.deleteConfirmOpen = false;
5949
+ /** Whether the currently mounted body has been init()'d. Reset on every mode switch. */
5950
+ this.listInited = false;
5951
+ this.tableInited = false;
5952
+ this.escapeHandler = null;
5953
+ this.openCreate = () => {
5954
+ if (!this.canAdd)
5955
+ return;
5956
+ this.editingHref = null;
5957
+ this.dialogBody = '';
5958
+ this.dialogTitle = '';
5959
+ this.dialogLabels = [];
5960
+ this.dialogImportant = false;
5961
+ this.dialogTouched = false;
5962
+ this.deleteConfirmOpen = false;
5963
+ this.dialogOpen = true;
5848
5964
  };
5849
- this.handleBlur = (e) => {
5850
- this.focused = false;
5851
- const raw = e.target.value;
5852
- const parsed = cellRenderer.parseLocalizedNumber(raw, this.locale);
5853
- if (this.required && (parsed === null || raw === '')) {
5854
- this.error = cellRenderer.t('required', this.locale);
5855
- }
5856
- else if (raw !== '' && !validateNumber(parsed, this.dataType)) {
5857
- this.error = cellRenderer.t('invalid_number', this.locale);
5965
+ /** Opens the same dialog pre-filled from an existing memo row/record —
5966
+ * triggered by clicking a card or a table row. No separate detail page. */
5967
+ this.openEdit = (row) => {
5968
+ var _a, _b;
5969
+ if (this.readOnly)
5970
+ return;
5971
+ const href = (_b = (_a = row === null || row === void 0 ? void 0 : row._links) === null || _a === void 0 ? void 0 : _a.self) === null || _b === void 0 ? void 0 : _b.href;
5972
+ if (!href)
5973
+ return;
5974
+ this.editingHref = href;
5975
+ const bodyRaw = this.slotValue(row, 'body');
5976
+ this.dialogBody = bodyRaw != null ? String(bodyRaw) : '';
5977
+ const titleRaw = this.slotValue(row, 'title');
5978
+ this.dialogTitle = titleRaw != null ? String(titleRaw) : '';
5979
+ const labelsRaw = this.slotValue(row, 'labels');
5980
+ this.dialogLabels = Array.isArray(labelsRaw)
5981
+ ? labelsRaw.map(String)
5982
+ : (labelsRaw != null && labelsRaw !== '' ? [String(labelsRaw)] : []);
5983
+ this.dialogImportant = !!this.slotValue(row, 'important');
5984
+ this.dialogTouched = false;
5985
+ this.deleteConfirmOpen = false;
5986
+ this.dialogOpen = true;
5987
+ };
5988
+ this.closeDialog = () => {
5989
+ this.dialogOpen = false;
5990
+ this.deleteConfirmOpen = false;
5991
+ };
5992
+ this.openDeleteConfirm = () => {
5993
+ this.deleteConfirmOpen = true;
5994
+ };
5995
+ this.cancelDeleteConfirm = () => {
5996
+ this.deleteConfirmOpen = false;
5997
+ };
5998
+ this.confirmDelete = () => {
5999
+ var _a;
6000
+ if (!this.editingHref)
6001
+ return;
6002
+ const href = this.editingHref;
6003
+ this.mrdDeleteObject.emit({ href });
6004
+ if (this.mode === 'cards') {
6005
+ (_a = this.listEl) === null || _a === void 0 ? void 0 : _a.removeRow(href);
5858
6006
  }
5859
6007
  else {
5860
- this.error = '';
5861
- }
5862
- if (parsed !== null && validateRequired(raw)) {
5863
- this.displayValue = this.formatForDisplay(parsed);
6008
+ this.refresh();
5864
6009
  }
5865
- this.mrdChange.emit({ name: this.name, value: parsed });
5866
- this.mrdBlur.emit({ name: this.name, value: parsed });
6010
+ this.deleteConfirmOpen = false;
6011
+ this.dialogOpen = false;
5867
6012
  };
5868
- this.handleFocus = () => {
5869
- this.focused = true;
5870
- // Drop the grouping separators while editing, but keep the locale's decimal
5871
- // separator: String(1234.56) would be re-read as 123456 where '.' groups.
5872
- const parsed = cellRenderer.parseLocalizedNumber(this.displayValue, this.locale);
5873
- if (parsed !== null) {
5874
- this.displayValue = cellRenderer.formatNumber(parsed, this.locale, { useGrouping: false, maximumFractionDigits: 20 });
6013
+ this.submitDialog = () => {
6014
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
6015
+ this.dialogTouched = true;
6016
+ if (!this.dialogBody.trim())
6017
+ return;
6018
+ const slots = (_b = (_a = this.archetype) === null || _a === void 0 ? void 0 : _a.slots) !== null && _b !== void 0 ? _b : {};
6019
+ if (this.editingHref) {
6020
+ // Every shown field is sent explicitly, even when cleared/unchecked —
6021
+ // this is a PATCH, so omitting a field would leave its old value intact.
6022
+ const values = { [(_c = slots.body) !== null && _c !== void 0 ? _c : 'body']: this.dialogBody };
6023
+ if (this.hasTitleSlot)
6024
+ values[(_d = slots.title) !== null && _d !== void 0 ? _d : 'title'] = this.dialogTitle.trim() || null;
6025
+ if (((_e = this.labelsListItems) !== null && _e !== void 0 ? _e : []).length)
6026
+ values[(_f = slots.labels) !== null && _f !== void 0 ? _f : 'labels'] = this.dialogLabels;
6027
+ if (this.hasImportantSlot)
6028
+ values[(_g = slots.important) !== null && _g !== void 0 ? _g : 'important'] = this.dialogImportant;
6029
+ this.mrdUpdateObject.emit({ href: this.editingHref, values });
6030
+ if (this.mode === 'cards') {
6031
+ (_h = this.listEl) === null || _h === void 0 ? void 0 : _h.patchRow(this.editingHref, values);
6032
+ }
6033
+ else {
6034
+ this.refresh();
6035
+ }
6036
+ }
6037
+ else {
6038
+ if (!this.canAdd)
6039
+ return;
6040
+ const values = {
6041
+ [(_j = slots.body) !== null && _j !== void 0 ? _j : 'body']: this.dialogBody,
6042
+ // now(), same token/format mrd-form's own defaultValue resolution uses.
6043
+ [(_k = slots.date) !== null && _k !== void 0 ? _k : 'date']: new Date().toISOString().replace(/\.\d{3}Z$/, 'Z'),
6044
+ };
6045
+ if (this.hasTitleSlot && this.dialogTitle.trim())
6046
+ values[(_l = slots.title) !== null && _l !== void 0 ? _l : 'title'] = this.dialogTitle.trim();
6047
+ if (((_m = this.labelsListItems) !== null && _m !== void 0 ? _m : []).length && this.dialogLabels.length)
6048
+ values[(_o = slots.labels) !== null && _o !== void 0 ? _o : 'labels'] = this.dialogLabels;
6049
+ if (this.hasImportantSlot && this.dialogImportant)
6050
+ values[(_p = slots.important) !== null && _p !== void 0 ? _p : 'important'] = true;
6051
+ if (this.meHref())
6052
+ values[(_q = slots.author) !== null && _q !== void 0 ? _q : 'author'] = this.meHref();
6053
+ // Always explicit — relation values are never inferred from the URL elsewhere
6054
+ // in this codebase (e.g. mrd-form's own submit payload), so don't assume it here.
6055
+ values[(_r = slots.container) !== null && _r !== void 0 ? _r : 'container'] = this.effectiveContainerHref;
6056
+ this.mrdCreateObject.emit({ path: this.buildCreatePath(), values });
5875
6057
  }
6058
+ this.dialogOpen = false;
5876
6059
  };
5877
6060
  }
5878
- componentWillLoad() {
5879
- this.syncFromValue();
5880
- }
5881
- /** Edit mode loads the record after mount, so the incoming value must re-sync. */
5882
- valueChanged() {
5883
- if (!this.focused)
5884
- this.syncFromValue();
5885
- }
5886
- localeChanged() {
5887
- if (!this.focused)
5888
- this.syncFromValue();
6061
+ disconnectedCallback() {
6062
+ this.unbindEscape();
6063
+ }
6064
+ /** Escape backs out of the delete-confirm step first (matches Cancel there),
6065
+ * or closes the whole dialog. Bound to `document` — bubbling from inside the
6066
+ * Quill editor is not reliable enough to rely on a local key handler. */
6067
+ dialogOpenChanged(open) {
6068
+ if (open) {
6069
+ this.escapeHandler = (e) => {
6070
+ if (e.key !== 'Escape')
6071
+ return;
6072
+ if (this.deleteConfirmOpen)
6073
+ this.cancelDeleteConfirm();
6074
+ else
6075
+ this.closeDialog();
6076
+ };
6077
+ document.addEventListener('keydown', this.escapeHandler);
6078
+ }
6079
+ else {
6080
+ this.unbindEscape();
6081
+ }
5889
6082
  }
5890
- syncFromValue() {
5891
- this.displayValue =
5892
- this.value !== null && this.value !== undefined ? this.formatForDisplay(this.value) : '';
6083
+ unbindEscape() {
6084
+ if (this.escapeHandler) {
6085
+ document.removeEventListener('keydown', this.escapeHandler);
6086
+ this.escapeHandler = null;
6087
+ }
5893
6088
  }
5894
- formatForDisplay(val) {
5895
- if (this.dataType === clientLayout.ClientLayoutItemFieldDataType.PERCENTAGE) {
5896
- return cellRenderer.formatNumber(val, this.locale, {
5897
- minimumFractionDigits: 0,
5898
- maximumFractionDigits: this.decimalPrecision,
5899
- }) + '%';
6089
+ /** Neither body self-loads: like mrd-table, both wait for init(). mrd-layout-section
6090
+ * init()s whichever is mounted at load time via its own querySelector pass; when the
6091
+ * user switches mode here, the freshly mounted body needs the same treatment. */
6092
+ componentDidRender() {
6093
+ var _a, _b;
6094
+ if (this.mode === 'cards' && this.listEl && !this.listInited) {
6095
+ this.listInited = true;
6096
+ const list = this.listEl;
6097
+ Promise.resolve((_a = list.componentOnReady) === null || _a === void 0 ? void 0 : _a.call(list)).then(() => list.init());
5900
6098
  }
5901
- if (this.dataType === clientLayout.ClientLayoutItemFieldDataType.DECIMAL) {
5902
- return cellRenderer.formatNumber(val, this.locale, {
5903
- minimumFractionDigits: this.decimalPrecision,
5904
- maximumFractionDigits: this.decimalPrecision,
5905
- });
6099
+ if (this.mode === 'table' && this.tableEl && !this.tableInited) {
6100
+ this.tableInited = true;
6101
+ const table = this.tableEl;
6102
+ Promise.resolve((_b = table.componentOnReady) === null || _b === void 0 ? void 0 : _b.call(table)).then(() => table.init());
5906
6103
  }
5907
- return cellRenderer.formatNumber(val, this.locale, { maximumFractionDigits: 0 });
6104
+ }
6105
+ setMode(mode) {
6106
+ if (mode === this.mode)
6107
+ return;
6108
+ this.listInited = false;
6109
+ this.tableInited = false;
6110
+ this.mode = mode;
6111
+ }
6112
+ /** Re-request page 0 of whichever body is currently mounted — called by
6113
+ * mrd-layout-section after a successful mrdCreateObject, and by this
6114
+ * component itself after an edit to a table row (which has no per-row
6115
+ * optimistic-patch method the way mrd-memo-list does). */
6116
+ async refresh() {
6117
+ if (this.mode === 'cards' && this.listEl) {
6118
+ await this.listEl.init();
6119
+ }
6120
+ else if (this.mode === 'table' && this.tableEl) {
6121
+ await this.tableEl.init();
6122
+ }
6123
+ }
6124
+ /** `me` is typed as RelationSearchResult ({ id, label }) but hosts differ on
6125
+ * which shape they actually populate: this repo's own dev preview resolves
6126
+ * it via /accounts/me as a real { id, label } RelationSearchResult, while
6127
+ * content-app feeds it from userProfile.links.person, the raw API link shape
6128
+ * ({ href, name }). Both occur in practice — same dual tolerance as
6129
+ * mrd-form's own getHref(). */
6130
+ meHref() {
6131
+ var _a, _b;
6132
+ const m = this.me;
6133
+ return (_b = (_a = m === null || m === void 0 ? void 0 : m.id) !== null && _a !== void 0 ? _a : m === null || m === void 0 ? void 0 : m.href) !== null && _b !== void 0 ? _b : '';
6134
+ }
6135
+ /** Value of a value-slot: reads row[field] via the slot→field map. */
6136
+ slotValue(row, slot) {
6137
+ var _a, _b;
6138
+ const field = (_b = (_a = this.archetype) === null || _a === void 0 ? void 0 : _a.slots) === null || _b === void 0 ? void 0 : _b[slot];
6139
+ if (!field)
6140
+ return undefined;
6141
+ return row[field];
6142
+ }
6143
+ get hasTitleSlot() {
6144
+ var _a, _b;
6145
+ return !!((_b = (_a = this.archetype) === null || _a === void 0 ? void 0 : _a.slots) === null || _b === void 0 ? void 0 : _b.title);
6146
+ }
6147
+ get hasImportantSlot() {
6148
+ var _a, _b;
6149
+ return !!((_b = (_a = this.archetype) === null || _a === void 0 ? void 0 : _a.slots) === null || _b === void 0 ? void 0 : _b.important);
6150
+ }
6151
+ /** A parent record already gives a new memo somewhere to attach to (RELATED_VIEW);
6152
+ * otherwise fall back to the account's own linked person (top-level VIEW). */
6153
+ get effectiveContainerHref() {
6154
+ return this.containerHref || this.meHref();
6155
+ }
6156
+ /** The author slot is always filled from `me` (there is no author picker in
6157
+ * the dialog), so without it there is nothing valid to create — regardless
6158
+ * of whether a parent record already supplies a container. */
6159
+ get canAdd() {
6160
+ return !this.readOnly && !!this.meHref() && !!this.effectiveContainerHref;
6161
+ }
6162
+ /** Path for creating a new memo: `/{dataClass}` for a top-level VIEW, or
6163
+ * `/{fromClass}/{parentId}/{dataClass}` when nested under a parent record. */
6164
+ buildCreatePath() {
6165
+ var _a, _b, _c, _d, _e, _f, _g;
6166
+ return buildListPath({
6167
+ isRelatedView: ((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === clientLayout.ClientLayoutItemType.RELATED_VIEW,
6168
+ fromClass: (_b = this.item) === null || _b === void 0 ? void 0 : _b.fromClass,
6169
+ parentId: this.parentId,
6170
+ dataClass: (_f = (_d = (_c = this.item) === null || _c === void 0 ? void 0 : _c.filterClass) !== null && _d !== void 0 ? _d : (_e = this.item) === null || _e === void 0 ? void 0 : _e.dataClass) !== null && _f !== void 0 ? _f : (_g = this.item) === null || _g === void 0 ? void 0 : _g.relatedClass,
6171
+ });
6172
+ }
6173
+ renderToolbar() {
6174
+ return (index.h("div", { class: "mrd-memo-container__toolbar" }, this.mode === 'cards' && (index.h("button", { type: "button", class: "mrd-memo-container__action", disabled: !this.canAdd, title: this.readOnly ? cellRenderer.t('readonly_access', this.locale) : undefined, onClick: this.openCreate }, 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: "M12 5v14M5 12h14" })), cellRenderer.t('memo_new', this.locale))), index.h("div", { class: "mrd-memo-container__seg", role: "group", "aria-label": cellRenderer.t('doc_view_switch', this.locale) }, index.h("button", { class: "mrd-memo-container__seg-btn", "aria-pressed": String(this.mode === 'cards'), title: cellRenderer.t('memo_view_cards', this.locale), "aria-label": cellRenderer.t('memo_view_cards', this.locale), onClick: () => this.setMode('cards') }, 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("rect", { x: "3", y: "4", width: "7", height: "7", rx: "1" }), index.h("rect", { x: "14", y: "4", width: "7", height: "7", rx: "1" }), index.h("rect", { x: "3", y: "15", width: "7", height: "5", rx: "1" }), index.h("rect", { x: "14", y: "15", width: "7", height: "5", rx: "1" }))), index.h("button", { class: "mrd-memo-container__seg-btn", "aria-pressed": String(this.mode === 'table'), title: cellRenderer.t('memo_view_table', this.locale), "aria-label": cellRenderer.t('memo_view_table', this.locale), onClick: () => this.setMode('table') }, 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: "M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01" }))))));
6175
+ }
6176
+ renderDeleteConfirm() {
6177
+ return (index.h("div", null, index.h("h2", { class: "mrd-memo-container__modal-title" }, cellRenderer.t('memo_delete_confirm_title', this.locale)), index.h("p", { class: "mrd-memo-container__modal-warning" }, cellRenderer.t('memo_delete_confirm_body', this.locale)), index.h("div", { class: "mrd-memo-container__modal-actions" }, index.h("button", { type: "button", class: "mrd-memo-container__modal-cancel", onClick: this.cancelDeleteConfirm }, cellRenderer.t('cancel', this.locale)), index.h("button", { type: "button", class: "mrd-memo-container__modal-delete-confirm", onClick: this.confirmDelete }, cellRenderer.t('delete', this.locale)))));
6178
+ }
6179
+ renderForm() {
6180
+ var _a, _b, _c;
6181
+ const bodyMissing = this.dialogTouched && !this.dialogBody.trim();
6182
+ return [
6183
+ index.h("h2", { class: "mrd-memo-container__modal-title" }, cellRenderer.t(this.editingHref ? 'memo_edit' : 'memo_new', this.locale)),
6184
+ index.h("div", { class: "mrd-memo-container__modal-field" }, index.h("mrd-textarea-field", { key: (_a = this.editingHref) !== null && _a !== void 0 ? _a : 'new', name: "body", value: this.dialogBody, required: true, autofocus: true, locale: this.locale, onMrdChange: (e) => { this.dialogBody = e.detail.value; } }), bodyMissing && index.h("span", { class: "mrd-memo-container__modal-error" }, cellRenderer.t('required', this.locale))),
6185
+ this.hasTitleSlot && (index.h("div", { class: "mrd-memo-container__modal-field" }, index.h("mrd-text-field", { name: "title", label: cellRenderer.t('memo_field_title', this.locale), value: this.dialogTitle, locale: this.locale, onMrdChange: (e) => { this.dialogTitle = e.detail.value; } }))),
6186
+ !!((_b = this.labelsListItems) !== null && _b !== void 0 ? _b : []).length && (index.h("div", { class: "mrd-memo-container__modal-field" }, index.h("mrd-list-field", { name: "labels", label: cellRenderer.t('memo_field_labels', this.locale), value: this.dialogLabels, multiple: true, listItems: (_c = this.labelsListItems) !== null && _c !== void 0 ? _c : [], locale: this.locale, onMrdChange: (e) => {
6187
+ this.dialogLabels = Array.isArray(e.detail.value) ? e.detail.value : [e.detail.value].filter(Boolean);
6188
+ } }))),
6189
+ this.hasImportantSlot && (index.h("div", { class: "mrd-memo-container__modal-field" }, index.h("mrd-boolean-field", { name: "important", label: cellRenderer.t('memo_important', this.locale), value: this.dialogImportant, locale: this.locale, onMrdChange: (e) => { this.dialogImportant = e.detail.value; } }))),
6190
+ index.h("div", { class: "mrd-memo-container__modal-actions" }, this.editingHref && (index.h("button", { type: "button", class: "mrd-memo-container__modal-delete", onClick: this.openDeleteConfirm }, cellRenderer.t('delete', this.locale))), index.h("button", { type: "button", class: "mrd-memo-container__modal-cancel", onClick: this.closeDialog }, cellRenderer.t('cancel', this.locale)), index.h("button", { type: "button", class: "mrd-memo-container__modal-submit", onClick: this.submitDialog }, cellRenderer.t('submit', this.locale))),
6191
+ ];
6192
+ }
6193
+ renderDialog() {
6194
+ if (!this.dialogOpen)
6195
+ return null;
6196
+ return (index.h("div", { class: "mrd-memo-container__modal-backdrop", onClick: this.closeDialog }, index.h("div", { class: "mrd-memo-container__modal", onClick: (e) => e.stopPropagation() }, this.deleteConfirmOpen ? this.renderDeleteConfirm() : this.renderForm())));
6197
+ }
6198
+ renderCards() {
6199
+ return (index.h("mrd-memo-list", { "data-view": this.viewKey, ref: el => (this.listEl = el), item: this.item, archetype: this.archetype, parentId: this.parentId, locale: this.locale, readOnly: this.readOnly, labelsListItems: this.labelsListItems, onMrdLoadPage: (e) => {
6200
+ e.stopPropagation();
6201
+ this.mrdLoadPage.emit(e.detail);
6202
+ }, onMrdEdit: (e) => {
6203
+ e.stopPropagation();
6204
+ this.openEdit(e.detail.row);
6205
+ } }));
6206
+ }
6207
+ renderTable() {
6208
+ return (index.h("mrd-table", { "data-view": this.viewKey, ref: el => (this.tableEl = el), item: this.item, parentId: this.parentId, locale: this.locale, readOnly: this.readOnly, onMrdLoadPage: (e) => {
6209
+ e.stopPropagation();
6210
+ this.mrdLoadPage.emit(e.detail);
6211
+ }, onMrdLoadAggregations: (e) => {
6212
+ e.stopPropagation();
6213
+ this.mrdLoadAggregations.emit(e.detail);
6214
+ }, onMrdRowClick: (e) => {
6215
+ e.stopPropagation();
6216
+ this.openEdit(e.detail.row);
6217
+ }, onMrdAction: (e) => {
6218
+ e.stopPropagation();
6219
+ this.mrdAction.emit(e.detail);
6220
+ } }));
5908
6221
  }
5909
6222
  render() {
5910
- const hasError = !!this.error;
5911
- const suffix = this.dataType === clientLayout.ClientLayoutItemFieldDataType.PERCENTAGE ? '%' :
5912
- this.dataType === clientLayout.ClientLayoutItemFieldDataType.DECIMAL ? '' : '';
5913
- return (index.h(index.Host, { key: '7343dbca882b5054f22de17672ac748a8e3eca11' }, index.h("div", { key: 'cef10b39515b48fc9c44e651910c6a0c2a847628', class: "mrd-number-field" }, index.h(FieldLabel, { key: '66f178cf20f1f2f0587bd9614db150d6ae63023e', base: "mrd-number-field", label: this.label, required: this.required }), index.h("div", { key: 'c57c22e663a570f6e5a70b07b817970f135e850c', class: "mrd-number-field__input-wrapper" }, index.h("input", { key: '388b20ac11fa4aaf78df124c858b579e12f53619', 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: 'f99bb85668b047a97162ffee2582eb45dc0589ae', base: "mrd-number-field", error: this.error }))));
6223
+ return (index.h(index.Host, { key: 'cf5e9a23e1e8496d061c00218029ec49d92700fe' }, this.renderToolbar(), index.h("div", { key: '5a15a60ea4cc68c77a8928068f7d6d6c3cb91434', class: "mrd-memo-container__body" }, this.mode === 'cards' ? this.renderCards() : this.renderTable()), this.renderDialog()));
5914
6224
  }
5915
6225
  static get watchers() { return {
5916
- "value": [{
5917
- "valueChanged": 0
5918
- }],
5919
- "locale": [{
5920
- "localeChanged": 0
6226
+ "dialogOpen": [{
6227
+ "dialogOpenChanged": 0
5921
6228
  }]
5922
6229
  }; }
5923
6230
  };
5924
- MrdNumberField.style = mrdNumberFieldCss();
5925
-
5926
- 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}.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-item--highlighted.sc-mrd-relation-field{background-color:var(--mrd-color-primary-light)}.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__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}@keyframes mrd-spin{to{transform:rotate(360deg)}}`;
6231
+ MrdMemoContainer.style = mrdMemoContainerCss();
5927
6232
 
5928
- const MrdRelationField = class {
5929
- constructor(hostRef) {
5930
- index.registerInstance(this, hostRef);
5931
- this.mrdChange = index.createEvent(this, "mrdChange");
5932
- this.mrdBlur = index.createEvent(this, "mrdBlur");
5933
- this.mrdSearch = index.createEvent(this, "mrdSearch");
5934
- this.mrdFetchAll = index.createEvent(this, "mrdFetchAll");
5935
- this.name = '';
5936
- this.label = '';
5937
- this.required = false;
5938
- this.disabled = false;
5939
- this.locale = navigator.language;
5940
- this.relatedClass = '';
5941
- /** When set, used instead of relatedClass for search queries (mostSignificantClass from API). */
5942
- this.mostSignificantClass = '';
5943
- this.displayType = clientLayout.ClientLayoutItemRelationDisplayType.SEARCH;
5944
- this.multiple = false;
5945
- this.dropdownValues = [];
5946
- /** Plain href string/array for normal use; pass { id, label } objects to pre-fill a loaded record. */
5947
- this.value = null;
5948
- this.searchQuery = '';
5949
- this.searchResults = [];
5950
- this.allRecords = [];
5951
- this.isLoading = false;
5952
- this.selectedItems = [];
5953
- this.showResults = false;
5954
- this.error = '';
5955
- this.highlightedIndex = -1;
5956
- this.searchDebounce = null;
5957
- this.handleKeyDown = (e) => {
5958
- if (!this.showResults || this.searchResults.length === 0) {
5959
- if (e.key === 'Escape') {
5960
- this.showResults = false;
5961
- this.highlightedIndex = -1;
5962
- }
5963
- return;
5964
- }
5965
- if (e.key === 'ArrowDown') {
5966
- e.preventDefault();
5967
- this.highlightedIndex = Math.min(this.highlightedIndex + 1, this.searchResults.length - 1);
5968
- }
5969
- else if (e.key === 'ArrowUp') {
5970
- e.preventDefault();
5971
- this.highlightedIndex = Math.max(this.highlightedIndex - 1, 0);
5972
- }
6233
+ /**
6234
+ * Pure sort/filter/aggregation query logic for mrd-table.
6235
+ * No component state — everything is passed in.
6236
+ */
6237
+ const TEXT_TYPES = new Set(['TEXT', 'TEXTBLOCK', 'EMAIL', 'HYPERLINK']);
6238
+ const NUMERIC_TYPES = new Set(['INTEGER', 'DECIMAL', 'PERCENTAGE', 'CURRENCY']);
6239
+ const DATE_TYPES = new Set(['DATE', 'DATETIME', 'TIME']);
6240
+ const NO_FILTER_TYPES = new Set(['FILE', 'IMAGE']);
6241
+ /** Column types that cannot be sorted or filtered (not stored in PostgreSQL). */
6242
+ const NON_INTERACTIVE_TYPES = new Set(['LONGTEXT', 'JSON', 'FILE', 'IMAGE']);
6243
+ /** Wait this long (ms) after the user stops typing in the free-text search box
6244
+ * before firing the search request — mirrors REQUEST_DEBOUNCE_MS's purpose
6245
+ * (skip intermediate keystrokes) but is tuned for typing, not scrolling. */
6246
+ const SEARCH_DEBOUNCE_MS = 400;
6247
+ function parseDefaultSort(defaultSort) {
6248
+ var _a;
6249
+ if (!defaultSort)
6250
+ return { field: '', dir: 'asc' };
6251
+ const parts = defaultSort.split(',');
6252
+ return { field: parts[0].trim(), dir: ((_a = parts[1]) === null || _a === void 0 ? void 0 : _a.trim()) === 'desc' ? 'desc' : 'asc' };
6253
+ }
6254
+ /** Raw sort query-param value, e.g. "name" or "name,desc". */
6255
+ function buildSortParam(field, dir) {
6256
+ if (!field)
6257
+ return '';
6258
+ return dir === 'desc' ? `${field},desc` : field;
6259
+ }
6260
+ /** Query params for a page request: page + sort + filterClass + view filters + active column filters. */
6261
+ function buildTableQueryParams(opts) {
6262
+ var _a, _b;
6263
+ const p = new URLSearchParams();
6264
+ if (opts.page > 0)
6265
+ p.set('page', String(opts.page));
6266
+ if (opts.sort)
6267
+ p.set('sort', opts.sort);
6268
+ if (opts.filterClass)
6269
+ p.set('type', opts.filterClass);
6270
+ applyViewFilters(p, opts.viewFilters);
6271
+ if (opts.query)
6272
+ p.set('q', opts.query);
6273
+ for (const f of opts.activeFilters) {
6274
+ if (f.operator === 'isEmpty') {
6275
+ p.set(f.field, '');
6276
+ continue;
6277
+ }
6278
+ if (f.operator === 'isNotEmpty') {
6279
+ p.set(f.field + '_notempty', 'true');
6280
+ continue;
6281
+ }
6282
+ if (f.operator === 'startsWith') {
6283
+ p.set(f.field + '_startswith', String((_a = f.value) !== null && _a !== void 0 ? _a : ''));
6284
+ continue;
6285
+ }
6286
+ if ((_b = f.values) === null || _b === void 0 ? void 0 : _b.length) {
6287
+ p.set(f.field, f.values.join(','));
6288
+ continue;
6289
+ }
6290
+ if (f.value != null)
6291
+ p.set(f.field, String(f.value));
6292
+ if (f.from != null)
6293
+ p.set(f.field + '_from', String(f.from));
6294
+ if (f.to != null)
6295
+ p.set(f.field + '_to', String(f.to));
6296
+ }
6297
+ return p.toString();
6298
+ }
6299
+ /** Groups aggregate columns by function; null when the view has no aggregates. */
6300
+ function buildAggregationParams(columns) {
6301
+ var _a;
6302
+ const groups = { sum: [], avg: [], count: [] };
6303
+ for (const col of columns) {
6304
+ if (col.type !== 'FIELD' || !col.aggregate)
6305
+ continue;
6306
+ const fn = col.aggregate.toLowerCase();
6307
+ if (fn in groups)
6308
+ groups[fn].push((_a = col.name) !== null && _a !== void 0 ? _a : '');
6309
+ }
6310
+ const params = {};
6311
+ if (groups.sum.length)
6312
+ params.sum = groups.sum;
6313
+ if (groups.avg.length)
6314
+ params.avg = groups.avg;
6315
+ if (groups.count.length)
6316
+ params.count = groups.count;
6317
+ return Object.keys(params).length > 0 ? params : null;
6318
+ }
6319
+ /** Aggregation query string: the page-0 query params without page/sort, plus sum/avg/count. */
6320
+ function buildAggregationQs(basePageQs, columns) {
6321
+ var _a, _b, _c;
6322
+ const p = new URLSearchParams(basePageQs);
6323
+ p.delete('page');
6324
+ p.delete('sort');
6325
+ const groups = buildAggregationParams(columns);
6326
+ if ((_a = groups === null || groups === void 0 ? void 0 : groups.sum) === null || _a === void 0 ? void 0 : _a.length)
6327
+ p.set('sum', groups.sum.join(','));
6328
+ if ((_b = groups === null || groups === void 0 ? void 0 : groups.avg) === null || _b === void 0 ? void 0 : _b.length)
6329
+ p.set('avg', groups.avg.join(','));
6330
+ if ((_c = groups === null || groups === void 0 ? void 0 : groups.count) === null || _c === void 0 ? void 0 : _c.length)
6331
+ p.set('count', groups.count.join(','));
6332
+ return p.toString();
6333
+ }
6334
+ /** True when the pending filter actually constrains anything. */
6335
+ function filterHasValue(f) {
6336
+ if (f.operator === 'isEmpty' || f.operator === 'isNotEmpty')
6337
+ return true;
6338
+ if (f.values !== undefined && f.values.length > 0)
6339
+ return true;
6340
+ if (f.value != null && f.value !== '')
6341
+ return true;
6342
+ if (typeof f.value === 'boolean')
6343
+ return true;
6344
+ if (f.from != null && f.from !== '')
6345
+ return true;
6346
+ if (f.to != null && f.to !== '')
6347
+ return true;
6348
+ return false;
6349
+ }
6350
+ // ── DATETIME filters: the user edits local "YYYY-MM-DD" dates, the API stores UTC ISO ──
6351
+ /** UTC ISO string at the start (midnight) of the given local day. */
6352
+ function dateLocalToUTCStart(dateStr) {
6353
+ if (!dateStr)
6354
+ return dateStr;
6355
+ const [year, month, day] = dateStr.split('-').map(Number);
6356
+ return new Date(year, month - 1, day).toISOString().replace(/\.\d{3}Z$/, 'Z');
6357
+ }
6358
+ /** Start of the day AFTER the given local date (exclusive range end). */
6359
+ function dateLocalToUTCEndExclusive(dateStr) {
6360
+ if (!dateStr)
6361
+ return dateStr;
6362
+ const [year, month, day] = dateStr.split('-').map(Number);
6363
+ return new Date(year, month - 1, day + 1).toISOString().replace(/\.\d{3}Z$/, 'Z');
6364
+ }
6365
+ /** Stored UTC ISO string back to the local "YYYY-MM-DD" date. */
6366
+ function utcISOToLocalDate(utcStr) {
6367
+ if (!utcStr)
6368
+ return utcStr;
6369
+ const d = new Date(utcStr);
6370
+ if (isNaN(d.getTime()))
6371
+ return utcStr;
6372
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
6373
+ }
6374
+ /** The stored "to" is the exclusive end (next midnight); subtract a day to recover the entered date. */
6375
+ function utcISOToLocalDateExclusiveEnd(utcStr) {
6376
+ if (!utcStr)
6377
+ return utcStr;
6378
+ const d = new Date(utcStr);
6379
+ if (isNaN(d.getTime()))
6380
+ return utcStr;
6381
+ d.setDate(d.getDate() - 1);
6382
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
6383
+ }
6384
+ /** Applies the local→UTC conversion when a DATETIME filter is submitted.
6385
+ * Exact date → range covering the full local day. */
6386
+ function normalizeDatetimeFilter(f) {
6387
+ const normalized = Object.assign({}, f);
6388
+ if (f.dataType === 'DATETIME' && f.operator !== 'isEmpty' && f.operator !== 'isNotEmpty') {
6389
+ if (typeof normalized.value === 'string' && normalized.value) {
6390
+ normalized.from = dateLocalToUTCStart(normalized.value);
6391
+ normalized.to = dateLocalToUTCEndExclusive(normalized.value);
6392
+ normalized.value = undefined;
6393
+ }
6394
+ else {
6395
+ if (typeof normalized.from === 'string' && normalized.from)
6396
+ normalized.from = dateLocalToUTCStart(normalized.from);
6397
+ if (typeof normalized.to === 'string' && normalized.to)
6398
+ normalized.to = dateLocalToUTCEndExclusive(normalized.to);
6399
+ }
6400
+ }
6401
+ return normalized;
6402
+ }
6403
+ /** Converts a stored DATETIME filter back to local dates for the popup.
6404
+ * A range covering a single local day is restored to exact-date mode. */
6405
+ function datetimeFilterToDisplay(existing) {
6406
+ const display = Object.assign({}, existing);
6407
+ if (typeof display.from === 'string' && display.from)
6408
+ display.from = utcISOToLocalDate(display.from);
6409
+ if (typeof display.to === 'string' && display.to)
6410
+ display.to = utcISOToLocalDateExclusiveEnd(display.to);
6411
+ if (display.from && display.to && display.from === display.to) {
6412
+ return Object.assign(Object.assign({}, display), { value: display.from, from: undefined, to: undefined });
6413
+ }
6414
+ return display;
6415
+ }
6416
+
6417
+ const mrdMemoListCss = () => `@charset "UTF-8";.sc-mrd-memo-list-h{display:block}.mrd-memo-list.sc-mrd-memo-list{display:flex;flex-direction:column;gap:var(--mrd-space-3)}.mrd-memo-list__card.sc-mrd-memo-list{display:flex;flex-direction:column;gap:var(--mrd-space-2);width:100%;padding:var(--mrd-space-4);background:var(--mrd-color-white);border:var(--mrd-border-width) solid var(--mrd-border-color);border-radius:var(--mrd-border-radius-md);font-family:var(--mrd-font-family);text-align:left;cursor:pointer;transition:border-color var(--mrd-transition), box-shadow var(--mrd-transition)}.mrd-memo-list__card.sc-mrd-memo-list:hover{border-color:var(--mrd-color-primary);box-shadow:var(--mrd-shadow-sm, 0 1px 2px rgba(0, 0, 0, 0.06))}.mrd-memo-list__card.sc-mrd-memo-list:focus-visible{outline:none;box-shadow:var(--mrd-shadow-focus)}.mrd-memo-list__card--readonly.sc-mrd-memo-list{cursor:default}.mrd-memo-list__card--readonly.sc-mrd-memo-list:hover{border-color:var(--mrd-border-color);box-shadow:none}.mrd-memo-list__card-header.sc-mrd-memo-list{display:flex;align-items:flex-start;justify-content:space-between;gap:var(--mrd-space-2)}.mrd-memo-list__card-title.sc-mrd-memo-list{font-size:var(--mrd-font-size-base);font-weight:var(--mrd-font-weight-semibold);color:var(--mrd-color-neutral-900)}.mrd-memo-list__card-important.sc-mrd-memo-list{display:inline-flex;flex-shrink:0;color:var(--mrd-color-warning)}.mrd-memo-list__card-important.sc-mrd-memo-list svg.sc-mrd-memo-list{width:1rem;height:1rem}.mrd-memo-list__card-body-wrap.sc-mrd-memo-list{display:flex;flex-direction:column;align-items:flex-start;gap:var(--mrd-space-1)}.mrd-memo-list__card-body.sc-mrd-memo-list{margin:0;font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-600);line-height:var(--mrd-line-height-relaxed);word-break:break-word}.mrd-memo-list__card-body.sc-mrd-memo-list p.sc-mrd-memo-list,.mrd-memo-list__card-body.sc-mrd-memo-list ul.sc-mrd-memo-list,.mrd-memo-list__card-body.sc-mrd-memo-list ol.sc-mrd-memo-list{margin:0 0 var(--mrd-space-1) 0}.mrd-memo-list__card-body--clamped.sc-mrd-memo-list{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.mrd-memo-list__card-toggle.sc-mrd-memo-list{background:none;border:none;padding:0;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);cursor:pointer}.mrd-memo-list__card-toggle.sc-mrd-memo-list:hover{text-decoration:underline}.mrd-memo-list__labels.sc-mrd-memo-list{display:flex;flex-wrap:wrap;gap:var(--mrd-space-2)}.mrd-memo-list__badge.sc-mrd-memo-list{display:inline-flex;align-items:center;height:1.25rem;padding:0 var(--mrd-space-2);border-radius:var(--mrd-border-radius-full, 999px);font-size:var(--mrd-font-size-xs);font-weight:var(--mrd-font-weight-medium)}.mrd-memo-list__badge--plain.sc-mrd-memo-list{background:var(--mrd-color-neutral-100);color:var(--mrd-color-neutral-600)}.mrd-memo-list__card-meta.sc-mrd-memo-list{display:flex;align-items:center;gap:var(--mrd-space-2);font-size:var(--mrd-font-size-xs);color:var(--mrd-color-neutral-400)}.mrd-memo-list__card-author.sc-mrd-memo-list+.mrd-memo-list__card-date.sc-mrd-memo-list::before{content:"·";margin-right:var(--mrd-space-2)}.mrd-memo-list__empty.sc-mrd-memo-list{padding:var(--mrd-space-6);text-align:center;color:var(--mrd-color-neutral-400);font-size:var(--mrd-font-size-sm)}.mrd-memo-list__load-more.sc-mrd-memo-list{align-self:center;height:var(--mrd-input-height);padding:0 var(--mrd-space-6);background:transparent;color:var(--mrd-color-neutral-600);font-family:var(--mrd-font-family);font-size:var(--mrd-font-size-sm);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)}.mrd-memo-list__load-more.sc-mrd-memo-list:hover:not(:disabled){background-color:var(--mrd-color-neutral-100)}.mrd-memo-list__load-more.sc-mrd-memo-list:disabled{opacity:0.6;cursor:default}`;
6418
+
6419
+ /** Plain-text length above which a card's body is clamped with a show-more toggle. */
6420
+ const BODY_PREVIEW_THRESHOLD = 220;
6421
+ const MrdMemoList = class {
6422
+ constructor(hostRef) {
6423
+ index.registerInstance(this, hostRef);
6424
+ this.mrdLoadPage = index.createEvent(this, "mrdLoadPage");
6425
+ this.mrdEdit = index.createEvent(this, "mrdEdit");
6426
+ /** The VIEW or RELATED_VIEW layout item (dataClass, fromClass, view config). */
6427
+ this.item = null;
6428
+ /** Parent record id — required for RELATED_VIEW path building. */
6429
+ this.parentId = '';
6430
+ /** Records per page (must match API page size). */
6431
+ this.pageSize = 20;
6432
+ this.locale = navigator.language;
6433
+ /** When true, cards are not clickable (no mrdEdit) — matches mrd-table's own
6434
+ * readOnly gating on its create action. */
6435
+ this.readOnly = false;
6436
+ /** listItems of the FIELD bound to the `labels` slot, resolved by mrd-layout-section
6437
+ * from its own items array, same reason mrd-memo-view needs it. */
6438
+ this.labelsListItems = null;
6439
+ this.rows = [];
6440
+ this.loading = false;
6441
+ this.exhausted = false;
6442
+ this.started = false;
6443
+ this.expandedHrefs = new Set();
6444
+ this.nextPage = 0;
6445
+ this.loadMore = () => {
6446
+ if (this.loading || this.exhausted)
6447
+ return;
6448
+ this.emitLoadPage(this.nextPage);
6449
+ };
6450
+ this.toggleExpanded = (e, href) => {
6451
+ e.stopPropagation();
6452
+ const next = new Set(this.expandedHrefs);
6453
+ if (next.has(href))
6454
+ next.delete(href);
6455
+ else
6456
+ next.add(href);
6457
+ this.expandedHrefs = next;
6458
+ };
6459
+ }
6460
+ buildDataPath() {
6461
+ var _a, _b, _c, _d, _e;
6462
+ return buildListPath({
6463
+ isRelatedView: ((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === 'RELATED_VIEW',
6464
+ fromClass: (_b = this.item) === null || _b === void 0 ? void 0 : _b.fromClass,
6465
+ parentId: this.parentId,
6466
+ dataClass: (_d = (_c = this.item) === null || _c === void 0 ? void 0 : _c.dataClass) !== null && _d !== void 0 ? _d : (_e = this.item) === null || _e === void 0 ? void 0 : _e.relatedClass,
6467
+ });
6468
+ }
6469
+ sortParam() {
6470
+ var _a, _b, _c;
6471
+ const { field, dir } = parseDefaultSort((_c = (_b = (_a = this.item) === null || _a === void 0 ? void 0 : _a.view) === null || _b === void 0 ? void 0 : _b.defaultSort) !== null && _c !== void 0 ? _c : '');
6472
+ return buildSortParam(field, dir);
6473
+ }
6474
+ emitLoadPage(page) {
6475
+ var _a, _b, _c;
6476
+ this.loading = true;
6477
+ this.mrdLoadPage.emit({
6478
+ page,
6479
+ sort: this.sortParam(),
6480
+ path: this.buildDataPath(),
6481
+ qs: buildTableQueryParams({
6482
+ page,
6483
+ sort: this.sortParam(),
6484
+ filterClass: (_a = this.item) === null || _a === void 0 ? void 0 : _a.filterClass,
6485
+ viewFilters: (_c = (_b = this.item) === null || _b === void 0 ? void 0 : _b.view) === null || _c === void 0 ? void 0 : _c.filter,
6486
+ activeFilters: [],
6487
+ }),
6488
+ });
6489
+ }
6490
+ /** Reset and request page 0. Call after setting all props, mirrors mrd-table.init(). */
6491
+ async init() {
6492
+ this.rows = [];
6493
+ this.loading = false;
6494
+ this.exhausted = false;
6495
+ this.started = true;
6496
+ this.nextPage = 0;
6497
+ this.emitLoadPage(0);
6498
+ }
6499
+ /** Inject the rows for a page (0-based); page 0 replaces, later pages append. */
6500
+ async setPage(pageNumber, rows, hasNext) {
6501
+ this.loading = false;
6502
+ this.rows = pageNumber === 0 ? rows : [...this.rows, ...rows];
6503
+ this.nextPage = pageNumber + 1;
6504
+ this.exhausted = hasNext !== undefined ? !hasNext : rows.length < this.pageSize;
6505
+ }
6506
+ /** Optimistically merge an edit into the matching row — mrdUpdateObject's PATCH
6507
+ * is fire-and-forget on the host side, so this is what makes an edit visible
6508
+ * immediately rather than only after the next full reload. */
6509
+ async patchRow(href, values) {
6510
+ this.rows = this.rows.map(row => { var _a, _b; return ((_b = (_a = row === null || row === void 0 ? void 0 : row._links) === null || _a === void 0 ? void 0 : _a.self) === null || _b === void 0 ? void 0 : _b.href) === href ? Object.assign(Object.assign({}, row), values) : row; });
6511
+ }
6512
+ /** Optimistically drop a deleted row — mrdDeleteObject's DELETE is fire-and-
6513
+ * forget on the host side, same reasoning as patchRow(). */
6514
+ async removeRow(href) {
6515
+ this.rows = this.rows.filter(row => { var _a, _b; return ((_b = (_a = row === null || row === void 0 ? void 0 : row._links) === null || _a === void 0 ? void 0 : _a.self) === null || _b === void 0 ? void 0 : _b.href) !== href; });
6516
+ }
6517
+ /** Value of a value-slot: reads row[field] via the slot→field map. */
6518
+ slotValue(row, slot) {
6519
+ var _a, _b;
6520
+ const field = (_b = (_a = this.archetype) === null || _a === void 0 ? void 0 : _a.slots) === null || _b === void 0 ? void 0 : _b[slot];
6521
+ if (!field)
6522
+ return undefined;
6523
+ return row[field];
6524
+ }
6525
+ /** Relation link for a relation-slot: reads row._links[field]. */
6526
+ slotLink(row, slot) {
6527
+ var _a, _b, _c;
6528
+ const field = (_b = (_a = this.archetype) === null || _a === void 0 ? void 0 : _a.slots) === null || _b === void 0 ? void 0 : _b[slot];
6529
+ if (!field)
6530
+ return undefined;
6531
+ const links = ((_c = row === null || row === void 0 ? void 0 : row._links) !== null && _c !== void 0 ? _c : {});
6532
+ return links[field];
6533
+ }
6534
+ plainTextLength(row) {
6535
+ const raw = this.slotValue(row, 'body');
6536
+ if (raw == null || raw === '')
6537
+ return 0;
6538
+ return String(raw).replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim().length;
6539
+ }
6540
+ renderLabels(row) {
6541
+ const raw = this.slotValue(row, 'labels');
6542
+ const keys = Array.isArray(raw) ? raw.map(String) : (raw != null && raw !== '' ? [String(raw)] : []);
6543
+ if (!keys.length)
6544
+ return null;
6545
+ return (index.h("div", { class: "mrd-memo-list__labels" }, keys.map(key => {
6546
+ var _a, _b;
6547
+ const listItem = ((_a = this.labelsListItems) !== null && _a !== void 0 ? _a : []).find(li => li.key === key);
6548
+ const label = (_b = listItem === null || listItem === void 0 ? void 0 : listItem.label) !== null && _b !== void 0 ? _b : key;
6549
+ if ((listItem === null || listItem === void 0 ? void 0 : listItem.color) && (listItem === null || listItem === void 0 ? void 0 : listItem.backgroundColor)) {
6550
+ return (index.h("span", { key: key, class: "mrd-memo-list__badge", style: { color: listItem.color, backgroundColor: listItem.backgroundColor } }, label));
6551
+ }
6552
+ return index.h("span", { key: key, class: "mrd-memo-list__badge mrd-memo-list__badge--plain" }, label);
6553
+ })));
6554
+ }
6555
+ renderBody(row, href) {
6556
+ const raw = this.slotValue(row, 'body');
6557
+ if (raw == null || raw === '')
6558
+ return null;
6559
+ const expanded = this.expandedHrefs.has(href);
6560
+ const needsToggle = this.plainTextLength(row) > BODY_PREVIEW_THRESHOLD;
6561
+ return (index.h("div", { class: "mrd-memo-list__card-body-wrap" }, index.h("div", { class: {
6562
+ 'mrd-memo-list__card-body': true,
6563
+ 'mrd-memo-list__card-body--clamped': needsToggle && !expanded,
6564
+ }, innerHTML: purify.sanitize(String(raw)) }), needsToggle && (index.h("button", { type: "button", class: "mrd-memo-list__card-toggle", onClick: e => this.toggleExpanded(e, href) }, cellRenderer.t(expanded ? 'textblock_show_less' : 'textblock_show_more', this.locale)))));
6565
+ }
6566
+ renderCard(row, index$1) {
6567
+ var _a, _b, _c;
6568
+ const titleRaw = this.slotValue(row, 'title');
6569
+ const title = titleRaw != null && titleRaw !== '' ? String(titleRaw) : null;
6570
+ const dateRaw = this.slotValue(row, 'date');
6571
+ const author = this.slotLink(row, 'author');
6572
+ const important = !!this.slotValue(row, 'important');
6573
+ const href = (_c = (_b = (_a = row === null || row === void 0 ? void 0 : row._links) === null || _a === void 0 ? void 0 : _a.self) === null || _b === void 0 ? void 0 : _b.href) !== null && _c !== void 0 ? _c : '';
6574
+ return (index.h("div", { key: href || index$1, class: { 'mrd-memo-list__card': true, 'mrd-memo-list__card--readonly': this.readOnly }, role: this.readOnly ? undefined : 'button', tabIndex: this.readOnly ? undefined : 0, onClick: () => {
6575
+ if (!this.readOnly)
6576
+ this.mrdEdit.emit({ row });
6577
+ }, onKeyDown: e => {
6578
+ if (this.readOnly)
6579
+ return;
6580
+ if (e.key === 'Enter' || e.key === ' ') {
6581
+ e.preventDefault();
6582
+ this.mrdEdit.emit({ row });
6583
+ }
6584
+ } }, index.h("div", { class: "mrd-memo-list__card-header" }, title && index.h("span", { class: "mrd-memo-list__card-title" }, title), important && (index.h("span", { class: "mrd-memo-list__card-important", title: cellRenderer.t('memo_important', this.locale) }, index.h("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true" }, index.h("path", { d: "M12 2l2.9 6.26L22 9.27l-5 4.87L18.18 21 12 17.27 5.82 21 7 14.14l-5-4.87 7.1-1.01z" }))))), this.renderBody(row, href), this.renderLabels(row), index.h("div", { class: "mrd-memo-list__card-meta" }, (author === null || author === void 0 ? void 0 : author.name) && index.h("span", { class: "mrd-memo-list__card-author" }, author.name), dateRaw != null && dateRaw !== '' && (index.h("span", { class: "mrd-memo-list__card-date" }, cellRenderer.formatDateTime(dateRaw, this.locale))))));
6585
+ }
6586
+ render() {
6587
+ return (index.h(index.Host, { key: 'c4c5ce4e96bf2aa754d85b260db8920fdde9311d' }, index.h("div", { key: '0db49511231edbf946f98734e0bab91cbdf31795', class: "mrd-memo-list" }, this.rows.map((row, i) => this.renderCard(row, i)), this.started && !this.loading && this.rows.length === 0 && (index.h("div", { key: '2a7a027673d01d63523ce252fe2fbff8ba0515fd', class: "mrd-memo-list__empty" }, cellRenderer.t('no_results', this.locale))), !this.exhausted && this.rows.length > 0 && (index.h("button", { key: '45dfd4a9ccab721d422935c48509d46989c9a360', type: "button", class: "mrd-memo-list__load-more", disabled: this.loading, onClick: this.loadMore }, cellRenderer.t('load_more', this.locale))))));
6588
+ }
6589
+ };
6590
+ MrdMemoList.style = mrdMemoListCss();
6591
+
6592
+ const mrdMemoViewCss = () => `@charset "UTF-8";.sc-mrd-memo-view-h{display:block}.mrd-memo-view.sc-mrd-memo-view{max-width:720px;display:flex;flex-direction:column;gap:var(--mrd-space-3)}.mrd-memo-view__header.sc-mrd-memo-view{display:flex;align-items:baseline;flex-wrap:wrap;gap:var(--mrd-space-3)}.mrd-memo-view__title.sc-mrd-memo-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}.mrd-memo-view__important.sc-mrd-memo-view{display:inline-flex;align-items:center;gap:var(--mrd-space-1);font-size:var(--mrd-font-size-xs);font-weight:var(--mrd-font-weight-semibold);color:var(--mrd-color-warning);text-transform:uppercase;letter-spacing:0.04em}.mrd-memo-view__important.sc-mrd-memo-view svg.sc-mrd-memo-view{width:0.875rem;height:0.875rem}.mrd-memo-view__meta.sc-mrd-memo-view{display:flex;align-items:center;gap:var(--mrd-space-2);font-size:var(--mrd-font-size-sm);color:var(--mrd-color-neutral-400)}.mrd-memo-view__meta-author.sc-mrd-memo-view{background:none;border:none;padding:0;font-family:var(--mrd-font-family);font-size:inherit;font-weight:var(--mrd-font-weight-medium);color:var(--mrd-color-neutral-500);cursor:pointer}.mrd-memo-view__meta-author.sc-mrd-memo-view:hover{color:var(--mrd-color-primary);text-decoration:underline}.mrd-memo-view__meta-date.sc-mrd-memo-view::before{content:"·";margin-right:var(--mrd-space-2)}.mrd-memo-view__meta-author.sc-mrd-memo-view+.mrd-memo-view__meta-date.sc-mrd-memo-view::before{content:"·"}.mrd-memo-view__labels.sc-mrd-memo-view{display:flex;flex-wrap:wrap;gap:var(--mrd-space-2)}.mrd-memo-view__badge.sc-mrd-memo-view{display:inline-flex;align-items:center;height:1.375rem;padding:0 var(--mrd-space-2);border-radius:var(--mrd-border-radius-full, 999px);font-size:var(--mrd-font-size-xs);font-weight:var(--mrd-font-weight-medium)}.mrd-memo-view__badge--plain.sc-mrd-memo-view{background:var(--mrd-color-neutral-100);color:var(--mrd-color-neutral-600)}.mrd-memo-view__container-link.sc-mrd-memo-view{align-self:flex-start;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}.mrd-memo-view__container-link.sc-mrd-memo-view:hover{text-decoration:underline}.mrd-memo-view__divider.sc-mrd-memo-view{height:var(--mrd-border-width);background:var(--mrd-color-neutral-200)}.mrd-memo-view__body.sc-mrd-memo-view{font-size:var(--mrd-font-size-base);color:var(--mrd-color-neutral-800);line-height:var(--mrd-line-height-relaxed);word-break:break-word}`;
6593
+
6594
+ const MrdMemoView = class {
6595
+ constructor(hostRef) {
6596
+ index.registerInstance(this, hostRef);
6597
+ this.mrdNavigate = index.createEvent(this, "mrdNavigate");
6598
+ /** The data record from the /data endpoint. Fields keyed by name; relations under `_links`. */
6599
+ this.data = {};
6600
+ this.locale = navigator.language;
6601
+ /** listItems of the FIELD bound to the `labels` slot, resolved by mrd-layout-section
6602
+ * from its own items array (archetype metadata does not publish listItems), so the
6603
+ * label badges get a real label/color instead of the raw stored key. */
6604
+ this.labelsListItems = null;
6605
+ }
6606
+ /** Value of a value-slot: reads data[field] via the slot→field map. */
6607
+ slotValue(slot) {
6608
+ var _a, _b;
6609
+ const field = (_b = (_a = this.archetype) === null || _a === void 0 ? void 0 : _a.slots) === null || _b === void 0 ? void 0 : _b[slot];
6610
+ if (!field)
6611
+ return undefined;
6612
+ return this.data[field];
6613
+ }
6614
+ /** Relation link for a relation-slot: reads data._links[field]. */
6615
+ slotLink(slot) {
6616
+ var _a, _b, _c, _d;
6617
+ const field = (_b = (_a = this.archetype) === null || _a === void 0 ? void 0 : _a.slots) === null || _b === void 0 ? void 0 : _b[slot];
6618
+ if (!field)
6619
+ return undefined;
6620
+ const links = ((_d = (_c = this.data) === null || _c === void 0 ? void 0 : _c._links) !== null && _d !== void 0 ? _d : {});
6621
+ return links[field];
6622
+ }
6623
+ renderAuthor() {
6624
+ const link = this.slotLink('author');
6625
+ if (!(link === null || link === void 0 ? void 0 : link.href) || !link.name)
6626
+ return null;
6627
+ return (index.h("button", { type: "button", class: "mrd-memo-view__meta-author", onClick: () => this.mrdNavigate.emit({ href: link.href, label: link.name }) }, link.name));
6628
+ }
6629
+ renderContainer() {
6630
+ const link = this.slotLink('container');
6631
+ if (!(link === null || link === void 0 ? void 0 : link.href) || !link.name)
6632
+ return null;
6633
+ return (index.h("button", { type: "button", class: "mrd-memo-view__container-link", onClick: () => this.mrdNavigate.emit({ href: link.href, label: link.name }) }, link.name));
6634
+ }
6635
+ renderLabels() {
6636
+ const raw = this.slotValue('labels');
6637
+ const keys = Array.isArray(raw) ? raw.map(String) : (raw != null && raw !== '' ? [String(raw)] : []);
6638
+ if (!keys.length)
6639
+ return null;
6640
+ return (index.h("div", { class: "mrd-memo-view__labels" }, keys.map(key => {
6641
+ var _a, _b;
6642
+ const listItem = ((_a = this.labelsListItems) !== null && _a !== void 0 ? _a : []).find(li => li.key === key);
6643
+ const label = (_b = listItem === null || listItem === void 0 ? void 0 : listItem.label) !== null && _b !== void 0 ? _b : key;
6644
+ if ((listItem === null || listItem === void 0 ? void 0 : listItem.color) && (listItem === null || listItem === void 0 ? void 0 : listItem.backgroundColor)) {
6645
+ return (index.h("span", { key: key, class: "mrd-memo-view__badge", style: { color: listItem.color, backgroundColor: listItem.backgroundColor } }, label));
6646
+ }
6647
+ return index.h("span", { key: key, class: "mrd-memo-view__badge mrd-memo-view__badge--plain" }, label);
6648
+ })));
6649
+ }
6650
+ renderBody() {
6651
+ const bodyRaw = this.slotValue('body');
6652
+ if (bodyRaw == null || bodyRaw === '')
6653
+ return null;
6654
+ return index.h("div", { class: "mrd-memo-view__body", innerHTML: purify.sanitize(String(bodyRaw)) });
6655
+ }
6656
+ render() {
6657
+ const titleRaw = this.slotValue('title');
6658
+ const title = titleRaw != null && titleRaw !== '' ? String(titleRaw) : null;
6659
+ const dateRaw = this.slotValue('date');
6660
+ const important = !!this.slotValue('important');
6661
+ return (index.h(index.Host, { key: '4d8ed14c54449fbcfddc94a34dcfb220338f8bba' }, index.h("div", { key: '0e0456277715607580e5373ada10706db1067c7d', class: "mrd-memo-view" }, index.h("div", { key: 'd5c548617eca9a99eb34409b2082be025cfce2f4', class: "mrd-memo-view__header" }, title && index.h("h1", { key: '2ecd2eae3f8fdba310679515aa2fe76e02f0c2b2', class: "mrd-memo-view__title" }, title), important && (index.h("span", { key: 'e5e8284310ab6040f1677bc1241d04d65784c2da', class: "mrd-memo-view__important", title: cellRenderer.t('memo_important', this.locale) }, index.h("svg", { key: 'babe987244b384330533721276b5392c9fe72c5a', viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true" }, index.h("path", { key: '511956710ae8e440328f9e477551ba1c2d478f1a', d: "M12 2l2.9 6.26L22 9.27l-5 4.87L18.18 21 12 17.27 5.82 21 7 14.14l-5-4.87 7.1-1.01z" })), cellRenderer.t('memo_important', this.locale)))), index.h("div", { key: '41c25e5376d94078debaf62121b8bdf400511d16', class: "mrd-memo-view__meta" }, this.renderAuthor(), dateRaw != null && dateRaw !== '' && (index.h("span", { key: 'caff8047249745ca98da77b374438e58d150ad7f', class: "mrd-memo-view__meta-date" }, cellRenderer.formatDateTime(dateRaw, this.locale)))), this.renderLabels(), this.renderContainer(), index.h("div", { key: 'bfa4c55458ea19fb920338df9478006b1883e606', class: "mrd-memo-view__divider" }), this.renderBody())));
6662
+ }
6663
+ };
6664
+ MrdMemoView.style = mrdMemoViewCss();
6665
+
6666
+ 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)}`;
6667
+
6668
+ const MrdNumberField = class {
6669
+ constructor(hostRef) {
6670
+ index.registerInstance(this, hostRef);
6671
+ this.mrdChange = index.createEvent(this, "mrdChange");
6672
+ this.mrdBlur = index.createEvent(this, "mrdBlur");
6673
+ this.name = '';
6674
+ this.label = '';
6675
+ this.value = null;
6676
+ this.placeholder = '';
6677
+ this.required = false;
6678
+ this.disabled = false;
6679
+ this.locale = navigator.language;
6680
+ this.dataType = clientLayout.ClientLayoutItemFieldDataType.INTEGER;
6681
+ this.decimalPrecision = 2;
6682
+ this.displayValue = '';
6683
+ this.error = '';
6684
+ /** While focused the user owns the text; prop updates must not overwrite it. */
6685
+ this.focused = false;
6686
+ this.handleInput = (e) => {
6687
+ this.displayValue = e.target.value;
6688
+ };
6689
+ this.handleBlur = (e) => {
6690
+ this.focused = false;
6691
+ const raw = e.target.value;
6692
+ const parsed = cellRenderer.parseLocalizedNumber(raw, this.locale);
6693
+ if (this.required && (parsed === null || raw === '')) {
6694
+ this.error = cellRenderer.t('required', this.locale);
6695
+ }
6696
+ else if (raw !== '' && !validateNumber(parsed, this.dataType)) {
6697
+ this.error = cellRenderer.t('invalid_number', this.locale);
6698
+ }
6699
+ else {
6700
+ this.error = '';
6701
+ }
6702
+ if (parsed !== null && validateRequired(raw)) {
6703
+ this.displayValue = this.formatForDisplay(parsed);
6704
+ }
6705
+ this.mrdChange.emit({ name: this.name, value: parsed });
6706
+ this.mrdBlur.emit({ name: this.name, value: parsed });
6707
+ };
6708
+ this.handleFocus = () => {
6709
+ this.focused = true;
6710
+ // Drop the grouping separators while editing, but keep the locale's decimal
6711
+ // separator: String(1234.56) would be re-read as 123456 where '.' groups.
6712
+ const parsed = cellRenderer.parseLocalizedNumber(this.displayValue, this.locale);
6713
+ if (parsed !== null) {
6714
+ this.displayValue = cellRenderer.formatNumber(parsed, this.locale, { useGrouping: false, maximumFractionDigits: 20 });
6715
+ }
6716
+ };
6717
+ }
6718
+ componentWillLoad() {
6719
+ this.syncFromValue();
6720
+ }
6721
+ /** Edit mode loads the record after mount, so the incoming value must re-sync. */
6722
+ valueChanged() {
6723
+ if (!this.focused)
6724
+ this.syncFromValue();
6725
+ }
6726
+ localeChanged() {
6727
+ if (!this.focused)
6728
+ this.syncFromValue();
6729
+ }
6730
+ syncFromValue() {
6731
+ this.displayValue =
6732
+ this.value !== null && this.value !== undefined ? this.formatForDisplay(this.value) : '';
6733
+ }
6734
+ formatForDisplay(val) {
6735
+ if (this.dataType === clientLayout.ClientLayoutItemFieldDataType.PERCENTAGE) {
6736
+ return cellRenderer.formatNumber(val, this.locale, {
6737
+ minimumFractionDigits: 0,
6738
+ maximumFractionDigits: this.decimalPrecision,
6739
+ }) + '%';
6740
+ }
6741
+ if (this.dataType === clientLayout.ClientLayoutItemFieldDataType.DECIMAL) {
6742
+ return cellRenderer.formatNumber(val, this.locale, {
6743
+ minimumFractionDigits: this.decimalPrecision,
6744
+ maximumFractionDigits: this.decimalPrecision,
6745
+ });
6746
+ }
6747
+ return cellRenderer.formatNumber(val, this.locale, { maximumFractionDigits: 0 });
6748
+ }
6749
+ render() {
6750
+ const hasError = !!this.error;
6751
+ const suffix = this.dataType === clientLayout.ClientLayoutItemFieldDataType.PERCENTAGE ? '%' :
6752
+ this.dataType === clientLayout.ClientLayoutItemFieldDataType.DECIMAL ? '' : '';
6753
+ return (index.h(index.Host, { key: '7343dbca882b5054f22de17672ac748a8e3eca11' }, index.h("div", { key: 'cef10b39515b48fc9c44e651910c6a0c2a847628', class: "mrd-number-field" }, index.h(FieldLabel, { key: '66f178cf20f1f2f0587bd9614db150d6ae63023e', base: "mrd-number-field", label: this.label, required: this.required }), index.h("div", { key: 'c57c22e663a570f6e5a70b07b817970f135e850c', class: "mrd-number-field__input-wrapper" }, index.h("input", { key: '388b20ac11fa4aaf78df124c858b579e12f53619', 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: 'f99bb85668b047a97162ffee2582eb45dc0589ae', base: "mrd-number-field", error: this.error }))));
6754
+ }
6755
+ static get watchers() { return {
6756
+ "value": [{
6757
+ "valueChanged": 0
6758
+ }],
6759
+ "locale": [{
6760
+ "localeChanged": 0
6761
+ }]
6762
+ }; }
6763
+ };
6764
+ MrdNumberField.style = mrdNumberFieldCss();
6765
+
6766
+ 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}.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-item--highlighted.sc-mrd-relation-field{background-color:var(--mrd-color-primary-light)}.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__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}@keyframes mrd-spin{to{transform:rotate(360deg)}}`;
6767
+
6768
+ const MrdRelationField = class {
6769
+ constructor(hostRef) {
6770
+ index.registerInstance(this, hostRef);
6771
+ this.mrdChange = index.createEvent(this, "mrdChange");
6772
+ this.mrdBlur = index.createEvent(this, "mrdBlur");
6773
+ this.mrdSearch = index.createEvent(this, "mrdSearch");
6774
+ this.mrdFetchAll = index.createEvent(this, "mrdFetchAll");
6775
+ this.name = '';
6776
+ this.label = '';
6777
+ this.required = false;
6778
+ this.disabled = false;
6779
+ this.locale = navigator.language;
6780
+ this.relatedClass = '';
6781
+ /** When set, used instead of relatedClass for search queries (mostSignificantClass from API). */
6782
+ this.mostSignificantClass = '';
6783
+ this.displayType = clientLayout.ClientLayoutItemRelationDisplayType.SEARCH;
6784
+ this.multiple = false;
6785
+ this.dropdownValues = [];
6786
+ /** Plain href string/array for normal use; pass { id, label } objects to pre-fill a loaded record. */
6787
+ this.value = null;
6788
+ this.searchQuery = '';
6789
+ this.searchResults = [];
6790
+ this.allRecords = [];
6791
+ this.isLoading = false;
6792
+ this.selectedItems = [];
6793
+ this.showResults = false;
6794
+ this.error = '';
6795
+ this.highlightedIndex = -1;
6796
+ this.searchDebounce = null;
6797
+ this.handleKeyDown = (e) => {
6798
+ if (!this.showResults || this.searchResults.length === 0) {
6799
+ if (e.key === 'Escape') {
6800
+ this.showResults = false;
6801
+ this.highlightedIndex = -1;
6802
+ }
6803
+ return;
6804
+ }
6805
+ if (e.key === 'ArrowDown') {
6806
+ e.preventDefault();
6807
+ this.highlightedIndex = Math.min(this.highlightedIndex + 1, this.searchResults.length - 1);
6808
+ }
6809
+ else if (e.key === 'ArrowUp') {
6810
+ e.preventDefault();
6811
+ this.highlightedIndex = Math.max(this.highlightedIndex - 1, 0);
6812
+ }
5973
6813
  else if (e.key === 'Enter') {
5974
6814
  e.preventDefault();
5975
6815
  if (this.highlightedIndex >= 0) {
@@ -6213,189 +7053,12 @@ const MrdSecretField = class {
6213
7053
  };
6214
7054
  MrdSecretField.style = mrdSecretFieldCss();
6215
7055
 
6216
- /**
6217
- * Pure sort/filter/aggregation query logic for mrd-table.
6218
- * No component state — everything is passed in.
6219
- */
6220
- const TEXT_TYPES = new Set(['TEXT', 'TEXTBLOCK', 'EMAIL', 'HYPERLINK']);
6221
- const NUMERIC_TYPES = new Set(['INTEGER', 'DECIMAL', 'PERCENTAGE', 'CURRENCY']);
6222
- const DATE_TYPES = new Set(['DATE', 'DATETIME', 'TIME']);
6223
- const NO_FILTER_TYPES = new Set(['FILE', 'IMAGE']);
6224
- /** Column types that cannot be sorted or filtered (not stored in PostgreSQL). */
6225
- const NON_INTERACTIVE_TYPES = new Set(['LONGTEXT', 'JSON', 'FILE', 'IMAGE']);
6226
- function parseDefaultSort(defaultSort) {
6227
- var _a;
6228
- if (!defaultSort)
6229
- return { field: '', dir: 'asc' };
6230
- const parts = defaultSort.split(',');
6231
- return { field: parts[0].trim(), dir: ((_a = parts[1]) === null || _a === void 0 ? void 0 : _a.trim()) === 'desc' ? 'desc' : 'asc' };
6232
- }
6233
- /** Raw sort query-param value, e.g. "name" or "name,desc". */
6234
- function buildSortParam(field, dir) {
6235
- if (!field)
6236
- return '';
6237
- return dir === 'desc' ? `${field},desc` : field;
6238
- }
6239
- /** Query params for a page request: page + sort + filterClass + view filters + active column filters. */
6240
- function buildTableQueryParams(opts) {
6241
- var _a, _b;
6242
- const p = new URLSearchParams();
6243
- if (opts.page > 0)
6244
- p.set('page', String(opts.page));
6245
- if (opts.sort)
6246
- p.set('sort', opts.sort);
6247
- if (opts.filterClass)
6248
- p.set('type', opts.filterClass);
6249
- applyViewFilters(p, opts.viewFilters);
6250
- for (const f of opts.activeFilters) {
6251
- if (f.operator === 'isEmpty') {
6252
- p.set(f.field, '');
6253
- continue;
6254
- }
6255
- if (f.operator === 'isNotEmpty') {
6256
- p.set(f.field + '_notempty', 'true');
6257
- continue;
6258
- }
6259
- if (f.operator === 'startsWith') {
6260
- p.set(f.field + '_startswith', String((_a = f.value) !== null && _a !== void 0 ? _a : ''));
6261
- continue;
6262
- }
6263
- if ((_b = f.values) === null || _b === void 0 ? void 0 : _b.length) {
6264
- p.set(f.field, f.values.join(','));
6265
- continue;
6266
- }
6267
- if (f.value != null)
6268
- p.set(f.field, String(f.value));
6269
- if (f.from != null)
6270
- p.set(f.field + '_from', String(f.from));
6271
- if (f.to != null)
6272
- p.set(f.field + '_to', String(f.to));
6273
- }
6274
- return p.toString();
6275
- }
6276
- /** Groups aggregate columns by function; null when the view has no aggregates. */
6277
- function buildAggregationParams(columns) {
6278
- var _a;
6279
- const groups = { sum: [], avg: [], count: [] };
6280
- for (const col of columns) {
6281
- if (col.type !== 'FIELD' || !col.aggregate)
6282
- continue;
6283
- const fn = col.aggregate.toLowerCase();
6284
- if (fn in groups)
6285
- groups[fn].push((_a = col.name) !== null && _a !== void 0 ? _a : '');
6286
- }
6287
- const params = {};
6288
- if (groups.sum.length)
6289
- params.sum = groups.sum;
6290
- if (groups.avg.length)
6291
- params.avg = groups.avg;
6292
- if (groups.count.length)
6293
- params.count = groups.count;
6294
- return Object.keys(params).length > 0 ? params : null;
6295
- }
6296
- /** Aggregation query string: the page-0 query params without page/sort, plus sum/avg/count. */
6297
- function buildAggregationQs(basePageQs, columns) {
6298
- var _a, _b, _c;
6299
- const p = new URLSearchParams(basePageQs);
6300
- p.delete('page');
6301
- p.delete('sort');
6302
- const groups = buildAggregationParams(columns);
6303
- if ((_a = groups === null || groups === void 0 ? void 0 : groups.sum) === null || _a === void 0 ? void 0 : _a.length)
6304
- p.set('sum', groups.sum.join(','));
6305
- if ((_b = groups === null || groups === void 0 ? void 0 : groups.avg) === null || _b === void 0 ? void 0 : _b.length)
6306
- p.set('avg', groups.avg.join(','));
6307
- if ((_c = groups === null || groups === void 0 ? void 0 : groups.count) === null || _c === void 0 ? void 0 : _c.length)
6308
- p.set('count', groups.count.join(','));
6309
- return p.toString();
6310
- }
6311
- /** True when the pending filter actually constrains anything. */
6312
- function filterHasValue(f) {
6313
- if (f.operator === 'isEmpty' || f.operator === 'isNotEmpty')
6314
- return true;
6315
- if (f.values !== undefined && f.values.length > 0)
6316
- return true;
6317
- if (f.value != null && f.value !== '')
6318
- return true;
6319
- if (typeof f.value === 'boolean')
6320
- return true;
6321
- if (f.from != null && f.from !== '')
6322
- return true;
6323
- if (f.to != null && f.to !== '')
6324
- return true;
6325
- return false;
6326
- }
6327
- // ── DATETIME filters: the user edits local "YYYY-MM-DD" dates, the API stores UTC ISO ──
6328
- /** UTC ISO string at the start (midnight) of the given local day. */
6329
- function dateLocalToUTCStart(dateStr) {
6330
- if (!dateStr)
6331
- return dateStr;
6332
- const [year, month, day] = dateStr.split('-').map(Number);
6333
- return new Date(year, month - 1, day).toISOString().replace(/\.\d{3}Z$/, 'Z');
6334
- }
6335
- /** Start of the day AFTER the given local date (exclusive range end). */
6336
- function dateLocalToUTCEndExclusive(dateStr) {
6337
- if (!dateStr)
6338
- return dateStr;
6339
- const [year, month, day] = dateStr.split('-').map(Number);
6340
- return new Date(year, month - 1, day + 1).toISOString().replace(/\.\d{3}Z$/, 'Z');
6341
- }
6342
- /** Stored UTC ISO string back to the local "YYYY-MM-DD" date. */
6343
- function utcISOToLocalDate(utcStr) {
6344
- if (!utcStr)
6345
- return utcStr;
6346
- const d = new Date(utcStr);
6347
- if (isNaN(d.getTime()))
6348
- return utcStr;
6349
- return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
6350
- }
6351
- /** The stored "to" is the exclusive end (next midnight); subtract a day to recover the entered date. */
6352
- function utcISOToLocalDateExclusiveEnd(utcStr) {
6353
- if (!utcStr)
6354
- return utcStr;
6355
- const d = new Date(utcStr);
6356
- if (isNaN(d.getTime()))
6357
- return utcStr;
6358
- d.setDate(d.getDate() - 1);
6359
- return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
6360
- }
6361
- /** Applies the local→UTC conversion when a DATETIME filter is submitted.
6362
- * Exact date → range covering the full local day. */
6363
- function normalizeDatetimeFilter(f) {
6364
- const normalized = Object.assign({}, f);
6365
- if (f.dataType === 'DATETIME' && f.operator !== 'isEmpty' && f.operator !== 'isNotEmpty') {
6366
- if (typeof normalized.value === 'string' && normalized.value) {
6367
- normalized.from = dateLocalToUTCStart(normalized.value);
6368
- normalized.to = dateLocalToUTCEndExclusive(normalized.value);
6369
- normalized.value = undefined;
6370
- }
6371
- else {
6372
- if (typeof normalized.from === 'string' && normalized.from)
6373
- normalized.from = dateLocalToUTCStart(normalized.from);
6374
- if (typeof normalized.to === 'string' && normalized.to)
6375
- normalized.to = dateLocalToUTCEndExclusive(normalized.to);
6376
- }
6377
- }
6378
- return normalized;
6379
- }
6380
- /** Converts a stored DATETIME filter back to local dates for the popup.
6381
- * A range covering a single local day is restored to exact-date mode. */
6382
- function datetimeFilterToDisplay(existing) {
6383
- const display = Object.assign({}, existing);
6384
- if (typeof display.from === 'string' && display.from)
6385
- display.from = utcISOToLocalDate(display.from);
6386
- if (typeof display.to === 'string' && display.to)
6387
- display.to = utcISOToLocalDateExclusiveEnd(display.to);
6388
- if (display.from && display.to && display.from === display.to) {
6389
- return Object.assign(Object.assign({}, display), { value: display.from, from: undefined, to: undefined });
6390
- }
6391
- return display;
6392
- }
6393
-
6394
7056
  /**
6395
7057
  * Stateless render parts of mrd-table. All state and handlers stay in the
6396
7058
  * component; these components receive plain values and callbacks.
6397
7059
  */
6398
7060
  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" }))));
7061
+ const SearchIcon = ({ class: cls }) => (index.h("svg", { class: cls, viewBox: "0 0 24 24", width: "16", height: "16", "aria-hidden": "true" }, index.h("path", { fill: "currentColor", d: "M15.5 14h-.79l-.28-.27a6.5 6.5 0 1 0-.7.7l.27.28v.79l5 4.99L20.49 19zM9.5 14A4.5 4.5 0 1 1 14 9.5 4.5 4.5 0 0 1 9.5 14" })));
6399
7062
  const TEXTBLOCK_MAX = 200;
6400
7063
  const TableCell = ({ col, row, locale, onDownload, onOpenTextblock, onOpenJson }) => {
6401
7064
  var _a, _b, _c;
@@ -6475,11 +7138,14 @@ const JsonModal = ({ html, locale, onClose }) => {
6475
7138
  return null;
6476
7139
  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": cellRenderer.t('close', locale) }, "\u2715"), index.h("pre", { class: "mrd-table__modal-json", innerHTML: html }))));
6477
7140
  };
6478
- const Toolbar = ({ locale, filterCount, actions, views, activeViewIdx, viewPopoverOpen, createPickerOpen, createTypes, readOnly, cb }) => {
7141
+ const Toolbar = ({ locale, filterCount, actions, views, activeViewIdx, viewPopoverOpen, createPickerOpen, createTypes, readOnly, searchEnabled, searchOpen, searchQuery, cb }) => {
6479
7142
  var _a;
6480
7143
  const hasActions = actions.length > 0;
6481
7144
  const hasViewSwitcher = views.length > 1;
6482
- return (index.h("div", { class: "mrd-table__toolbar" }, index.h("div", { class: "mrd-table__toolbar-left" }, filterCount > 0 && (index.h("button", { class: "mrd-table__action mrd-table__action--secondary mrd-table__filter-clear", 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__filter-clear-label" }, cellRenderer.t('table_filter_clear_all', locale), " (", filterCount, ")")))), 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: () => {
7145
+ return (index.h("div", { class: "mrd-table__toolbar" }, index.h("div", { class: "mrd-table__toolbar-left" }, searchEnabled && (searchOpen ? (index.h("span", { class: "mrd-table__search-box" }, index.h(SearchIcon, null), index.h("input", { type: "text", class: "mrd-table__search-input", value: searchQuery !== null && searchQuery !== void 0 ? searchQuery : '', placeholder: cellRenderer.t('search_placeholder', locale), ref: cb.onSearchInputRef, onInput: (e) => cb.onSearchInput(e.target.value), onKeyDown: (e) => {
7146
+ if (e.key === 'Escape')
7147
+ cb.onCloseSearch();
7148
+ } }), index.h("button", { type: "button", class: "mrd-table__search-clear", "aria-label": cellRenderer.t('clear', locale), onClick: cb.onCloseSearch }, "\u2715"))) : (index.h("button", { type: "button", class: "mrd-table__action mrd-table__action--secondary mrd-table__search-toggle", onClick: cb.onToggleSearch }, index.h(SearchIcon, { class: "mrd-table__action-icon" }), index.h("span", { class: "mrd-table__action-tooltip" }, cellRenderer.t('table_search', locale))))), filterCount > 0 && (index.h("button", { class: "mrd-table__action mrd-table__action--secondary mrd-table__filter-clear", 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__filter-clear-label" }, cellRenderer.t('table_filter_clear_all', locale), " (", filterCount, ")")))), 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: () => {
6483
7149
  if (i !== activeViewIdx)
6484
7150
  cb.onViewSwitch(i);
6485
7151
  cb.onCloseViewPopover();
@@ -6653,7 +7319,7 @@ function getStalePages(requestedAt, now, timeoutMs) {
6653
7319
  return stale;
6654
7320
  }
6655
7321
 
6656
- const mrdTableCss = () => `.sc-mrd-table-h{display:block;width:100%}.mrd-table.sc-mrd-table{overflow-x:auto}.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__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;overflow:hidden;text-overflow:ellipsis;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--filtered.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__col-resizer.sc-mrd-table{position:absolute;top:0;right:0;width:9px;height:100%;cursor:col-resize;touch-action:none;user-select:none}.mrd-table__col-resizer.sc-mrd-table::after{content:"";position:absolute;top:25%;right:4px;width:1px;height:50%;background:var(--mrd-border-color)}.mrd-table__col-resizer.sc-mrd-table:hover::after{width:2px;right:3px;background:var(--mrd-color-primary)}.mrd-table__col-resizer--active.sc-mrd-table::after{width:2px;right:3px;height:100%;top:0;background:var(--mrd-color-primary)}.mrd-table--resizing.sc-mrd-table{cursor:col-resize;user-select:none}.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__row--loading.sc-mrd-table{background:transparent}.mrd-table__row--failed.sc-mrd-table{background:transparent}.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;overflow:hidden;text-overflow:ellipsis}.mrd-table__cell--numeric.sc-mrd-table{text-align:right;font-variant-numeric:tabular-nums}.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__cell--failed.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}.mrd-table__retry-button.sc-mrd-table{border:none;background:none;padding:0;color:var(--mrd-color-danger);font-size:inherit;cursor:pointer;text-decoration:underline}.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:hover .mrd-table__action-tooltip.sc-mrd-table{display:block}.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__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-clear.sc-mrd-table{width:auto;gap:var(--mrd-space-1);padding:0 var(--mrd-space-2);color:var(--mrd-color-primary);border-color:var(--mrd-color-primary)}.mrd-table__filter-clear.sc-mrd-table:hover{color:var(--mrd-color-primary);border-color:var(--mrd-color-primary)}.mrd-table__filter-clear-label.sc-mrd-table{font-size:var(--mrd-font-size-sm);white-space:nowrap}.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--stacked.sc-mrd-table{flex-direction:column;align-items:stretch;gap:var(--mrd-space-2)}.mrd-table__filter-range-sep.sc-mrd-table{color:var(--mrd-color-neutral-400);flex-shrink:0}.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;overflow:hidden;text-overflow:ellipsis;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}@keyframes mrd-shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}`;
7322
+ const mrdTableCss = () => `.sc-mrd-table-h{display:block;width:100%}.mrd-table.sc-mrd-table{overflow-x:auto}.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__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;overflow:hidden;text-overflow:ellipsis;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--filtered.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__col-resizer.sc-mrd-table{position:absolute;top:0;right:0;width:9px;height:100%;cursor:col-resize;touch-action:none;user-select:none}.mrd-table__col-resizer.sc-mrd-table::after{content:"";position:absolute;top:25%;right:4px;width:1px;height:50%;background:var(--mrd-border-color)}.mrd-table__col-resizer.sc-mrd-table:hover::after{width:2px;right:3px;background:var(--mrd-color-primary)}.mrd-table__col-resizer--active.sc-mrd-table::after{width:2px;right:3px;height:100%;top:0;background:var(--mrd-color-primary)}.mrd-table--resizing.sc-mrd-table{cursor:col-resize;user-select:none}.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__row--loading.sc-mrd-table{background:transparent}.mrd-table__row--failed.sc-mrd-table{background:transparent}.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;overflow:hidden;text-overflow:ellipsis}.mrd-table__cell--numeric.sc-mrd-table{text-align:right;font-variant-numeric:tabular-nums}.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__cell--failed.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}.mrd-table__retry-button.sc-mrd-table{border:none;background:none;padding:0;color:var(--mrd-color-danger);font-size:inherit;cursor:pointer;text-decoration:underline}.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:hover .mrd-table__action-tooltip.sc-mrd-table{display:block}.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__search-box.sc-mrd-table{display:inline-flex;align-items:center;gap:var(--mrd-space-1);height:2rem;padding:0 var(--mrd-space-2);border:1px solid var(--mrd-border-color-focus, var(--mrd-color-primary));border-radius:var(--mrd-border-radius);background:var(--mrd-color-white, #fff);box-shadow:var(--mrd-shadow-focus, none);color:var(--mrd-color-neutral-400)}.mrd-table__search-input.sc-mrd-table{border:none;outline:none;background:transparent;font-size:var(--mrd-font-size-sm);font-family:var(--mrd-font-family);color:var(--mrd-color-neutral-800);width:12rem}.mrd-table__search-clear.sc-mrd-table{display:inline-flex;align-items:center;justify-content:center;background:none;border:none;padding:0;cursor:pointer;color:var(--mrd-color-neutral-400);font-size:var(--mrd-font-size-xs);line-height:1}.mrd-table__search-clear.sc-mrd-table:hover{color:var(--mrd-color-neutral-700)}.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-clear.sc-mrd-table{width:auto;gap:var(--mrd-space-1);padding:0 var(--mrd-space-2);color:var(--mrd-color-primary);border-color:var(--mrd-color-primary)}.mrd-table__filter-clear.sc-mrd-table:hover{color:var(--mrd-color-primary);border-color:var(--mrd-color-primary)}.mrd-table__filter-clear-label.sc-mrd-table{font-size:var(--mrd-font-size-sm);white-space:nowrap}.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--stacked.sc-mrd-table{flex-direction:column;align-items:stretch;gap:var(--mrd-space-2)}.mrd-table__filter-range-sep.sc-mrd-table{color:var(--mrd-color-neutral-400);flex-shrink:0}.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;overflow:hidden;text-overflow:ellipsis;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}@keyframes mrd-shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}`;
6657
7323
 
6658
7324
  /** How often (ms) to scan outstanding page requests for staleness. */
6659
7325
  const STALE_CHECK_INTERVAL_MS = 2000;
@@ -6684,6 +7350,17 @@ const MrdTable = class {
6684
7350
  this.keydownHandler = null;
6685
7351
  this.createPickerClickHandler = null;
6686
7352
  this.viewPopoverClickHandler = null;
7353
+ /** Debounce timer for the free-text search box — separate from debounceTimer
7354
+ * (pending-page requests), since typing and scrolling debounce independently. */
7355
+ this.searchDebounceTimer = null;
7356
+ /** The rendered search <input>, captured so it can be focused the instant it mounts. */
7357
+ this.searchInputEl = null;
7358
+ /** Set by toggleSearch() when the box just expanded; consumed and cleared in componentDidRender(). */
7359
+ this.searchNeedsFocus = false;
7360
+ /** Column filters stashed by stashFiltersForSearch() while the search box is open — the
7361
+ * backend can't combine `q` with column filters. Restored by restoreFiltersAfterSearch()
7362
+ * on close, unless the user applied a fresh filter of their own in the meantime. */
7363
+ this.stashedFilters = null;
6687
7364
  /** Watches the host for gaining a box (e.g. its tab pane being shown) — see componentDidLoad. */
6688
7365
  this.resizeObserver = null;
6689
7366
  /** Guards against scheduling more than one column-width measurement per freeze. */
@@ -6738,6 +7415,10 @@ const MrdTable = class {
6738
7415
  this.sortDir = 'asc';
6739
7416
  /** Active filters keyed by field name. */
6740
7417
  this.activeFilters = new Map();
7418
+ /** True while the toolbar's magnifying glass is expanded into the search input. */
7419
+ this.searchOpen = false;
7420
+ /** Current free-text search query — sent as `q` on every mrdLoadPage/aggregations request. */
7421
+ this.searchQuery = '';
6741
7422
  /** Field name of the currently open filter popup (null = closed). */
6742
7423
  this.openFilterCol = null;
6743
7424
  /** Filter state being edited in the open popup. */
@@ -6791,6 +7472,11 @@ const MrdTable = class {
6791
7472
  this.colWidthMeasureScheduled = false;
6792
7473
  this.colWidthsUserSet = false;
6793
7474
  this.fixedContentMeasured = false;
7475
+ // A new item is a different table (possibly not even a VIEW any more) — a leftover
7476
+ // query from the old one should not silently keep filtering it.
7477
+ this.searchOpen = false;
7478
+ this.searchQuery = '';
7479
+ this.stashedFilters = null;
6794
7480
  }
6795
7481
  // ── Lifecycle ──────────────────────────────────────────────────────────────
6796
7482
  componentWillLoad() {
@@ -6898,7 +7584,12 @@ const MrdTable = class {
6898
7584
  if (pageNumber === 0 && this.aggregationsPending) {
6899
7585
  this.aggregationsPending = false;
6900
7586
  const hasAggColumns = this.columns.some(c => c.type === 'FIELD' && c.aggregate);
6901
- if (!isLastPage || hasAggColumns) {
7587
+ // The aggregations endpoint doesn't support the `q` free-text param, so a request
7588
+ // sent while searching would silently return unfiltered totals. Leave aggregations
7589
+ // (and aggregationsTotal) at null instead — TotalsRow already renders nothing when
7590
+ // aggregations is null, so the totals row just disappears for the duration of the
7591
+ // search rather than showing numbers that don't match the filtered rows.
7592
+ if (!this.searchQuery && (!isLastPage || hasAggColumns)) {
6902
7593
  this.emitLoadAggregations();
6903
7594
  }
6904
7595
  }
@@ -6937,10 +7628,18 @@ const MrdTable = class {
6937
7628
  document.removeEventListener('click', this.viewPopoverClickHandler);
6938
7629
  this.viewPopoverClickHandler = null;
6939
7630
  }
7631
+ if (this.searchDebounceTimer !== null) {
7632
+ clearTimeout(this.searchDebounceTimer);
7633
+ this.searchDebounceTimer = null;
7634
+ }
6940
7635
  }
6941
7636
  componentDidRender() {
6942
7637
  this.freezeColWidths();
6943
7638
  this.growToFixedContent();
7639
+ if (this.searchNeedsFocus && this.searchInputEl) {
7640
+ this.searchInputEl.focus();
7641
+ this.searchNeedsFocus = false;
7642
+ }
6944
7643
  }
6945
7644
  /** Freeze the column widths once the first data page has rendered.
6946
7645
  *
@@ -7231,16 +7930,19 @@ const MrdTable = class {
7231
7930
  });
7232
7931
  }
7233
7932
  buildActionDetail(action, basicType) {
7234
- var _a, _b, _c;
7933
+ var _a;
7235
7934
  if (action === 'export') {
7236
7935
  return { action, path: this.buildExcelPath(), qs: this.buildQueryParams(0) };
7237
7936
  }
7238
7937
  if (action === 'create') {
7239
7938
  const v = this.allViews[this.activeViewIdx];
7240
- const parentPath = ((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === 'RELATED_VIEW'
7241
- ? `/${(_b = v === null || v === void 0 ? void 0 : v.fromClass) !== null && _b !== void 0 ? _b : ''}/${this.parentId}`
7242
- : null;
7243
- return Object.assign({ action, dataClass: (_c = v === null || v === void 0 ? void 0 : v.dataClass) !== null && _c !== void 0 ? _c : '', parentPath }, (basicType ? { basicType } : {}));
7939
+ return buildCreateActionDetail({
7940
+ isRelatedView: ((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === 'RELATED_VIEW',
7941
+ fromClass: v === null || v === void 0 ? void 0 : v.fromClass,
7942
+ parentId: this.parentId,
7943
+ dataClass: v === null || v === void 0 ? void 0 : v.dataClass,
7944
+ basicType,
7945
+ });
7244
7946
  }
7245
7947
  return { action };
7246
7948
  }
@@ -7259,7 +7961,13 @@ const MrdTable = class {
7259
7961
  dataClass: v.dataClass,
7260
7962
  });
7261
7963
  }
7262
- /** Build query params for a page request from current sort, view filters, filterClass and active column filters. */
7964
+ /** Build query params for a page request from current sort, view filters, filterClass and active column filters.
7965
+ *
7966
+ * `q` and column filters are mutually exclusive on the backend — combining them breaks
7967
+ * the search. stashFiltersForSearch() already empties activeFilters for the duration of
7968
+ * a search, but this guard is the actual guarantee: even if a filter is applied through
7969
+ * a column header while the search box is still open (before the query is cleared),
7970
+ * activeFilters is dropped from the request rather than sent alongside `q`. */
7263
7971
  buildQueryParams(page) {
7264
7972
  var _a;
7265
7973
  const v = this.allViews[this.activeViewIdx];
@@ -7268,7 +7976,8 @@ const MrdTable = class {
7268
7976
  sort: this.sortParam(),
7269
7977
  filterClass: v === null || v === void 0 ? void 0 : v.filterClass,
7270
7978
  viewFilters: (_a = v === null || v === void 0 ? void 0 : v.view) === null || _a === void 0 ? void 0 : _a.filter,
7271
- activeFilters: this.activeFilters.values(),
7979
+ activeFilters: this.searchQuery ? [] : this.activeFilters.values(),
7980
+ query: this.searchQuery,
7272
7981
  });
7273
7982
  }
7274
7983
  /** True when the table is in paginated / virtual-scroll mode rather than driven by the
@@ -7574,6 +8283,18 @@ const MrdTable = class {
7574
8283
  const current = (_b = (_a = this.pendingFilter) === null || _a === void 0 ? void 0 : _a.values) !== null && _b !== void 0 ? _b : [];
7575
8284
  this.pendingFilter = Object.assign(Object.assign({}, this.pendingFilter), { values: checked ? [...current, key] : current.filter(k => k !== key) });
7576
8285
  }
8286
+ /** Common reload after activeFilters or searchQuery changed: drop stale aggregations
8287
+ * (the next setPage(0) re-requests them, guarded against `q` in setPage() itself) and
8288
+ * re-fetch page 0. Shared by the filter popup, clear-all, and free-text search. */
8289
+ reloadAfterQueryChange() {
8290
+ this.aggregations = null;
8291
+ this.aggregationsTotal = null;
8292
+ this.aggregationsPending = true;
8293
+ if (this.isPaginated) {
8294
+ this.resetPages();
8295
+ this.emitPagesForWindow(this.renderStart, this.renderEnd);
8296
+ }
8297
+ }
7577
8298
  applyFilter() {
7578
8299
  const f = this.pendingFilter;
7579
8300
  if (!(f === null || f === void 0 ? void 0 : f.field)) {
@@ -7590,13 +8311,7 @@ const MrdTable = class {
7590
8311
  }
7591
8312
  this.activeFilters = next;
7592
8313
  this.closeFilterPopup();
7593
- this.aggregations = null;
7594
- this.aggregationsTotal = null;
7595
- this.aggregationsPending = true;
7596
- if (this.isPaginated) {
7597
- this.resetPages();
7598
- this.emitPagesForWindow(this.renderStart, this.renderEnd);
7599
- }
8314
+ this.reloadAfterQueryChange();
7600
8315
  }
7601
8316
  clearFilter() {
7602
8317
  const name = this.openFilterCol;
@@ -7605,23 +8320,80 @@ const MrdTable = class {
7605
8320
  next.delete(name);
7606
8321
  this.activeFilters = next;
7607
8322
  this.closeFilterPopup();
7608
- this.aggregations = null;
7609
- this.aggregationsTotal = null;
7610
- this.aggregationsPending = true;
7611
- if (this.isPaginated) {
7612
- this.resetPages();
7613
- this.emitPagesForWindow(this.renderStart, this.renderEnd);
7614
- }
8323
+ this.reloadAfterQueryChange();
7615
8324
  }
7616
8325
  clearAllFilters() {
7617
8326
  this.activeFilters = new Map();
7618
- this.aggregations = null;
7619
- this.aggregationsTotal = null;
7620
- this.aggregationsPending = true;
7621
- if (this.isPaginated) {
7622
- this.resetPages();
7623
- this.emitPagesForWindow(this.renderStart, this.renderEnd);
8327
+ this.reloadAfterQueryChange();
8328
+ }
8329
+ // ── Free-text search ───────────────────────────────────────────────────────
8330
+ /** Search is a VIEW-only affordance — a RELATED_VIEW table is already scoped to
8331
+ * its parent record, so a free-text box there would invite confusion about what
8332
+ * it searches across. */
8333
+ get searchEnabled() {
8334
+ var _a;
8335
+ return ((_a = this.item) === null || _a === void 0 ? void 0 : _a.type) === 'VIEW';
8336
+ }
8337
+ toggleSearch() {
8338
+ if (this.searchOpen) {
8339
+ this.closeSearch();
8340
+ }
8341
+ else {
8342
+ this.searchOpen = true;
8343
+ this.searchNeedsFocus = true;
8344
+ this.stashFiltersForSearch();
8345
+ }
8346
+ }
8347
+ /** Collapses the box back to the icon. Clearing a non-empty query and restoring any
8348
+ * stashed filters can each independently require a reload — reloadAfterQueryChange()
8349
+ * is called at most once here regardless of how many of the two actually changed. */
8350
+ closeSearch() {
8351
+ this.searchOpen = false;
8352
+ if (this.searchDebounceTimer !== null) {
8353
+ clearTimeout(this.searchDebounceTimer);
8354
+ this.searchDebounceTimer = null;
7624
8355
  }
8356
+ const hadQuery = this.searchQuery !== '';
8357
+ this.searchQuery = '';
8358
+ const filtersRestored = this.restoreFiltersAfterSearch();
8359
+ if (hadQuery || filtersRestored)
8360
+ this.reloadAfterQueryChange();
8361
+ }
8362
+ handleSearchInput(value) {
8363
+ this.searchQuery = value;
8364
+ if (this.searchDebounceTimer !== null)
8365
+ clearTimeout(this.searchDebounceTimer);
8366
+ this.searchDebounceTimer = setTimeout(() => this.applySearch(), SEARCH_DEBOUNCE_MS);
8367
+ }
8368
+ /** Reloads from page 0 with the current searchQuery, same reset as applyFilter(). */
8369
+ applySearch() {
8370
+ this.searchDebounceTimer = null;
8371
+ this.reloadAfterQueryChange();
8372
+ }
8373
+ /** Column filters and the free-text `q` param are mutually exclusive on the backend —
8374
+ * sending both breaks the search. Opening the search box stashes any active filters
8375
+ * and clears them (the header filter icons and the clear-all button disappear along
8376
+ * with activeFilters, so there is nothing extra to hide) and reloads unfiltered. */
8377
+ stashFiltersForSearch() {
8378
+ if (this.activeFilters.size === 0)
8379
+ return;
8380
+ this.stashedFilters = this.activeFilters;
8381
+ this.activeFilters = new Map();
8382
+ this.reloadAfterQueryChange();
8383
+ }
8384
+ /** Restores filters stashed by stashFiltersForSearch(), unless the user applied a fresh
8385
+ * filter of their own while the search box was open — that explicit choice wins over
8386
+ * reinstating the old one. Returns whether activeFilters actually changed, so the
8387
+ * caller can decide whether a reload is needed. */
8388
+ restoreFiltersAfterSearch() {
8389
+ if (!this.stashedFilters)
8390
+ return false;
8391
+ const stashed = this.stashedFilters;
8392
+ this.stashedFilters = null;
8393
+ if (this.activeFilters.size > 0)
8394
+ return false;
8395
+ this.activeFilters = stashed;
8396
+ return true;
7625
8397
  }
7626
8398
  // ── View switcher ──────────────────────────────────────────────────────────
7627
8399
  handleViewSwitch(targetIdx) {
@@ -7632,6 +8404,9 @@ const MrdTable = class {
7632
8404
  this.activeViewIdx = targetIdx;
7633
8405
  this.applyDefaultSort((_b = (_a = target.view) === null || _a === void 0 ? void 0 : _a.defaultSort) !== null && _b !== void 0 ? _b : '');
7634
8406
  this.activeFilters = new Map();
8407
+ this.searchOpen = false;
8408
+ this.searchQuery = '';
8409
+ this.stashedFilters = null;
7635
8410
  this.init();
7636
8411
  }
7637
8412
  toggleViewPopover(e) {
@@ -7654,7 +8429,7 @@ const MrdTable = class {
7654
8429
  // ── Render: toolbar ────────────────────────────────────────────────────────
7655
8430
  renderToolbar() {
7656
8431
  var _a;
7657
- return (index.h(Toolbar, { locale: this.locale, 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, readOnly: this.readOnly, cb: {
8432
+ return (index.h(Toolbar, { locale: this.locale, 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, readOnly: this.readOnly, searchEnabled: this.searchEnabled, searchOpen: this.searchOpen, searchQuery: this.searchQuery, cb: {
7658
8433
  onClearAllFilters: () => this.clearAllFilters(),
7659
8434
  onViewSwitch: idx => this.handleViewSwitch(idx),
7660
8435
  onToggleViewPopover: e => this.toggleViewPopover(e),
@@ -7665,6 +8440,10 @@ const MrdTable = class {
7665
8440
  this.closeCreatePicker();
7666
8441
  },
7667
8442
  onAction: action => this.mrdAction.emit(this.buildActionDetail(action)),
8443
+ onToggleSearch: () => this.toggleSearch(),
8444
+ onSearchInput: value => this.handleSearchInput(value),
8445
+ onCloseSearch: () => this.closeSearch(),
8446
+ onSearchInputRef: el => (this.searchInputEl = el !== null && el !== void 0 ? el : null),
7668
8447
  } }));
7669
8448
  }
7670
8449
  // ── Render: filter popup ───────────────────────────────────────────────────
@@ -7855,12 +8634,29 @@ const MrdTextareaField = class {
7855
8634
  this.required = false;
7856
8635
  this.disabled = false;
7857
8636
  this.locale = navigator.language;
8637
+ /** Focus the editor as soon as it's ready — opt-in, since auto-focusing every
8638
+ * textarea field on mount would be wrong for a regular multi-field form. */
8639
+ this.autofocus = false;
7858
8640
  this.error = '';
7859
8641
  this.editorReady = false;
7860
8642
  }
7861
8643
  componentDidLoad() {
7862
8644
  this.initQuill();
7863
8645
  }
8646
+ /** The host may reuse the same element for a different record (e.g. mrd-memo-
8647
+ * container's quick-create/edit dialog editing a second memo without the
8648
+ * dialog itself remounting) — Quill only reads `value` once at construction,
8649
+ * so re-apply it here when it changes to something the editor doesn't already
8650
+ * hold. Guarded against our own emitted mrdChange feeding back in as a no-op. */
8651
+ valueChanged(newValue) {
8652
+ if (!this.editorReady || !this.quill)
8653
+ return;
8654
+ if (newValue === this.getSanitizedHtml())
8655
+ return;
8656
+ this.quill.setText('');
8657
+ if (newValue)
8658
+ this.quill.clipboard.dangerouslyPasteHTML(newValue);
8659
+ }
7864
8660
  async initQuill() {
7865
8661
  try {
7866
8662
  // Dynamically import Quill
@@ -7882,6 +8678,7 @@ const MrdTextareaField = class {
7882
8678
  ],
7883
8679
  },
7884
8680
  });
8681
+ this.quill = quill;
7885
8682
  if (this.value) {
7886
8683
  quill.clipboard.dangerouslyPasteHTML(this.value);
7887
8684
  }
@@ -7897,6 +8694,8 @@ const MrdTextareaField = class {
7897
8694
  }
7898
8695
  });
7899
8696
  this.editorReady = true;
8697
+ if (this.autofocus)
8698
+ quill.focus();
7900
8699
  }
7901
8700
  catch (err) {
7902
8701
  console.error('Failed to load Quill editor:', err);
@@ -7908,9 +8707,14 @@ const MrdTextareaField = class {
7908
8707
  return purify.sanitize(html);
7909
8708
  }
7910
8709
  render() {
7911
- return (index.h(index.Host, { key: 'e132531881f68f373e700617aac8033c8ebccb47' }, index.h("div", { key: 'fec0cf56cd7868d3fcd5a4e8a382b2dcdb6e5c50', class: "mrd-textarea-field" }, index.h(FieldLabel, { key: '333aa2ff57cce9e3178f0c4be4a1df1077884248', base: "mrd-textarea-field", label: this.label, required: this.required }), index.h("div", { key: '40025207580eb5768981b85aaa0a8ff95fce7234', class: controlClass('mrd-textarea-field', !!this.error, 'container') }, index.h("div", { key: '621987b3b2b1d8b4836bff065075ba527a82db81', class: "mrd-textarea-field__editor" })), index.h(FieldError, { key: 'ac2d8de22f008cd1c91842137ccd0cd36eb9ce19', base: "mrd-textarea-field", error: this.error }))));
8710
+ return (index.h(index.Host, { key: '5dad54667601fce064107311e741e4e0dad94298' }, index.h("div", { key: 'bd7bd538155ec3172fa8cc1cf4cf66ad23d07a3b', class: "mrd-textarea-field" }, index.h(FieldLabel, { key: 'a3fe2c714340bbdcd3521e9782f87f3773c65e62', base: "mrd-textarea-field", label: this.label, required: this.required }), index.h("div", { key: 'a7a628f94bc628fd358c7fc876ee1bdd2c7ef520', class: controlClass('mrd-textarea-field', !!this.error, 'container') }, index.h("div", { key: '30ecd27d9e928094178f8f011524ff5633cb875e', class: "mrd-textarea-field__editor" })), index.h(FieldError, { key: '589d5cbf28c3ae1bdbe5f663aaf6cae840bdcffe', base: "mrd-textarea-field", error: this.error }))));
7912
8711
  }
7913
8712
  get el() { return index.getElement(this); }
8713
+ static get watchers() { return {
8714
+ "value": [{
8715
+ "valueChanged": 0
8716
+ }]
8717
+ }; }
7914
8718
  };
7915
8719
  MrdTextareaField.style = mrdTextareaFieldCss();
7916
8720
 
@@ -7962,6 +8766,9 @@ exports.mrd_invoice_view = MrdInvoiceView;
7962
8766
  exports.mrd_layout_section = MrdLayoutSection;
7963
8767
  exports.mrd_list_field = MrdListField;
7964
8768
  exports.mrd_longtext_field = MrdLongtextField;
8769
+ exports.mrd_memo_container = MrdMemoContainer;
8770
+ exports.mrd_memo_list = MrdMemoList;
8771
+ exports.mrd_memo_view = MrdMemoView;
7965
8772
  exports.mrd_number_field = MrdNumberField;
7966
8773
  exports.mrd_relation_field = MrdRelationField;
7967
8774
  exports.mrd_secret_field = MrdSecretField;