@mmlogic/components 0.3.8 → 0.3.10

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 (82) hide show
  1. package/dist/cjs/index.cjs.js +13 -0
  2. package/dist/cjs/loader.cjs.js +1 -1
  3. package/dist/cjs/mosterdcomponents.cjs.js +1 -1
  4. package/dist/cjs/{mrd-boolean-field_20.cjs.entry.js → mrd-boolean-field_23.cjs.entry.js} +1059 -23
  5. package/dist/collection/collection-manifest.json +3 -0
  6. package/dist/collection/components/mrd-boolean-field/mrd-boolean-field.js +1 -1
  7. package/dist/collection/components/mrd-currency-field/mrd-currency-field.js +1 -1
  8. package/dist/collection/components/mrd-date-field/mrd-date-field.js +1 -1
  9. package/dist/collection/components/mrd-datetime-field/mrd-datetime-field.js +1 -1
  10. package/dist/collection/components/mrd-document-container/mrd-document-container.js +375 -0
  11. package/dist/collection/components/mrd-document-container/mrd-document-container.scss +79 -0
  12. package/dist/collection/components/mrd-document-list/mrd-document-list.js +1129 -0
  13. package/dist/collection/components/mrd-document-list/mrd-document-list.scss +181 -0
  14. package/dist/collection/components/mrd-document-view/mrd-document-view.js +177 -0
  15. package/dist/collection/components/mrd-document-view/mrd-document-view.scss +121 -0
  16. package/dist/collection/components/mrd-email-field/mrd-email-field.js +1 -1
  17. package/dist/collection/components/mrd-file-field/mrd-file-field.js +1 -1
  18. package/dist/collection/components/mrd-image-field/mrd-image-field.js +1 -1
  19. package/dist/collection/components/mrd-layout-section/mrd-layout-section.js +288 -14
  20. package/dist/collection/components/mrd-layout-section/mrd-layout-section.scss +2 -3
  21. package/dist/collection/components/mrd-longtext-field/mrd-longtext-field.js +1 -1
  22. package/dist/collection/components/mrd-number-field/mrd-number-field.js +1 -1
  23. package/dist/collection/components/mrd-secret-field/mrd-secret-field.js +2 -2
  24. package/dist/collection/components/mrd-text-field/mrd-text-field.js +1 -1
  25. package/dist/collection/components/mrd-textarea-field/mrd-textarea-field.js +1 -1
  26. package/dist/collection/components/mrd-time-field/mrd-time-field.js +1 -1
  27. package/dist/collection/dev/app.js +66 -2
  28. package/dist/collection/types/client-layout.js +10 -0
  29. package/dist/collection/utils/i18n.js +34 -0
  30. package/dist/components/client-layout.js +1 -1
  31. package/dist/components/format.js +1 -1
  32. package/dist/components/i18n.js +1 -1
  33. package/dist/components/index.js +1 -1
  34. package/dist/components/mrd-boolean-field2.js +1 -1
  35. package/dist/components/mrd-currency-field2.js +1 -1
  36. package/dist/components/mrd-date-field2.js +1 -1
  37. package/dist/components/mrd-datetime-field2.js +1 -1
  38. package/dist/components/mrd-document-container.d.ts +11 -0
  39. package/dist/components/mrd-document-container.js +1 -0
  40. package/dist/components/mrd-document-container2.js +1 -0
  41. package/dist/components/mrd-document-list.d.ts +11 -0
  42. package/dist/components/mrd-document-list.js +1 -0
  43. package/dist/components/mrd-document-list2.js +1 -0
  44. package/dist/components/mrd-document-view.d.ts +11 -0
  45. package/dist/components/mrd-document-view.js +1 -0
  46. package/dist/components/mrd-document-view2.js +1 -0
  47. package/dist/components/mrd-email-field2.js +1 -1
  48. package/dist/components/mrd-file-field2.js +1 -1
  49. package/dist/components/mrd-image-field2.js +1 -1
  50. package/dist/components/mrd-layout-section.js +1 -1
  51. package/dist/components/mrd-longtext-field2.js +1 -1
  52. package/dist/components/mrd-number-field2.js +1 -1
  53. package/dist/components/mrd-secret-field2.js +1 -1
  54. package/dist/components/mrd-table2.js +1 -1
  55. package/dist/components/mrd-text-field2.js +1 -1
  56. package/dist/components/mrd-textarea-field2.js +1 -1
  57. package/dist/components/mrd-time-field2.js +1 -1
  58. package/dist/esm/index.js +11 -1
  59. package/dist/esm/loader.js +1 -1
  60. package/dist/esm/mosterdcomponents.js +1 -1
  61. package/dist/esm/{mrd-boolean-field_20.entry.js → mrd-boolean-field_23.entry.js} +1058 -25
  62. package/dist/mosterdcomponents/{cell-renderer-CbRwLOo8.js.map → cell-renderer-B-AJDBcj.js.map} +1 -1
  63. package/dist/mosterdcomponents/{client-layout-D88nn5zf.js.map → client-layout-ChqRA3AF.js.map} +1 -1
  64. package/dist/mosterdcomponents/i18n-s1XrKcD2.js.map +1 -0
  65. package/dist/mosterdcomponents/index-DkY-NQj0.js.map +1 -0
  66. package/dist/mosterdcomponents/index-DwF_Sp__.js.map +1 -0
  67. package/dist/mosterdcomponents/index.esm.js +1 -1
  68. package/dist/mosterdcomponents/mosterdcomponents.css +1 -1
  69. package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
  70. package/dist/mosterdcomponents/p-69452249.entry.js +1 -0
  71. package/dist/mosterdcomponents/{validation-ixb43cqU.js.map → validation-Br9k2Ztw.js.map} +1 -1
  72. package/dist/types/components/mrd-document-container/mrd-document-container.d.ts +94 -0
  73. package/dist/types/components/mrd-document-list/mrd-document-list.d.ts +210 -0
  74. package/dist/types/components/mrd-document-view/mrd-document-view.d.ts +36 -0
  75. package/dist/types/components/mrd-layout-section/mrd-layout-section.d.ts +57 -6
  76. package/dist/types/components.d.ts +507 -15
  77. package/dist/types/types/client-layout.d.ts +38 -0
  78. package/package.json +1 -1
  79. package/dist/mosterdcomponents/i18n-hoGGKbKU.js.map +0 -1
  80. package/dist/mosterdcomponents/index-6yQUNVww.js.map +0 -1
  81. package/dist/mosterdcomponents/index-I5SuYv7a.js.map +0 -1
  82. package/dist/mosterdcomponents/p-7bfaee51.entry.js +0 -1
@@ -1,5 +1,5 @@
1
1
  import { Host, h } from "@stencil/core";
2
- import { ClientLayoutItemType, ClientLayoutItemFieldDataType, } from "../../types/client-layout";
2
+ import { ClientLayoutItemType, ClientLayoutItemFieldDataType, resolveArchetype, ARCHETYPE_DOCUMENT, } from "../../types/client-layout";
3
3
  import { CellRenderer } from "../../utils/cell-renderer";
4
4
  import { t } from "../../utils/i18n";
5
5
  import { formatDate } from "../../utils/format";
@@ -14,6 +14,9 @@ export class MrdLayoutSection {
14
14
  /** Legacy: top-level _links from ClientDashboardMetadata. Not needed in new flat format. */
15
15
  this.links = {};
16
16
  this.locale = navigator.language;
17
+ /** Top-level archetypes on the object dashboard. When it contains commons.document,
18
+ * the record is rendered as a single-document view instead of generic fields. */
19
+ this.archetypes = [];
17
20
  this.searchQueryMap = {};
18
21
  this.searchResultsMap = {};
19
22
  this.imagePreviewUrl = null;
@@ -102,11 +105,18 @@ export class MrdLayoutSection {
102
105
  }
103
106
  }
104
107
  /**
105
- * Inject data into an embedded mrd-table for a RELATED_VIEW or VIEW item.
106
- * Pass totalElements to update the pagination total (safe to pass on every page).
107
- * Pass hasNext (from _links.next presence) so the table can decide whether to emit aggregations.
108
+ * Inject rows for a VIEW / RELATED_VIEW item.
109
+ * - Table view: injects the page into the embedded mrd-table (pass totalElements/hasNext).
110
+ * - Document view: pass `nodeId` to route the rows to that folder node in the embedded
111
+ * mrd-document-list. Folder loading is just a filtered list load, so it reuses this method.
108
112
  */
109
- async setViewPage(name, page, rows, totalElements, hasNext) {
113
+ async setViewPage(name, page, rows, totalElements, hasNext, nodeId) {
114
+ if (nodeId) {
115
+ const list = this.el.querySelector(`mrd-document-list[data-doclist="${name}"]`);
116
+ if (list === null || list === void 0 ? void 0 : list.setDocuments)
117
+ await list.setDocuments(nodeId, rows);
118
+ return;
119
+ }
110
120
  const table = this.el.querySelector(`mrd-table[data-view="${name}"]`);
111
121
  if (!table)
112
122
  return;
@@ -122,6 +132,26 @@ export class MrdLayoutSection {
122
132
  return;
123
133
  await table.setAggregations(data);
124
134
  }
135
+ /** Inject distinct values into an embedded mrd-document-list for a document view. */
136
+ async setViewDistinct(name, nodeId, values) {
137
+ const list = this.el.querySelector(`mrd-document-list[data-doclist="${name}"]`);
138
+ if (list === null || list === void 0 ? void 0 : list.setDistinct)
139
+ await list.setDistinct(nodeId, values);
140
+ }
141
+ /** Inject the uploaded file reference for a dropped file, so the document view
142
+ * can request creation of the new document (see mrdViewUpload). */
143
+ async setViewFileReference(name, uri) {
144
+ const list = this.el.querySelector(`mrd-document-list[data-doclist="${name}"]`);
145
+ if (list === null || list === void 0 ? void 0 : list.setFileReference)
146
+ await list.setFileReference(uri);
147
+ }
148
+ /** Inject the created document's href after a file-drop create, so the
149
+ * optimistic row becomes navigable (see mrdCreateObject). */
150
+ async setViewCreatedObject(name, href) {
151
+ const list = this.el.querySelector(`mrd-document-list[data-doclist="${name}"]`);
152
+ if (list === null || list === void 0 ? void 0 : list.setCreatedHref)
153
+ await list.setCreatedHref(href);
154
+ }
125
155
  /** Provide a resolved URL for an IMAGE field. Shows as thumbnail; clicking opens the lightbox. */
126
156
  async setImagePreview(fieldName, url) {
127
157
  this.imagePreviews = Object.assign(Object.assign({}, this.imagePreviews), { [fieldName]: url });
@@ -270,7 +300,7 @@ export class MrdLayoutSection {
270
300
  return (h("div", { class: "mrd-layout-section__search", key: `search-${dataClass}` }, h("div", { class: "mrd-layout-section__search-wrap" }, 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" }, 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" })), 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 && (h("ul", { class: "mrd-layout-section__search-results" }, results.map(r => (h("li", { key: r.id, class: "mrd-layout-section__search-result" }, h("button", { class: "mrd-layout-section__search-result-btn", onClick: () => this.mrdNavigate.emit({ href: r.id, label: r.label }) }, h("span", { class: "mrd-layout-section__search-result-label" }, r.label), r.description && h("span", { class: "mrd-layout-section__search-result-desc" }, r.description)))))))));
271
301
  }
272
302
  renderRelatedView(item) {
273
- var _a, _b, _c, _d, _e, _f;
303
+ var _a, _b, _c, _d, _e, _f, _g, _h;
274
304
  const key = this.viewKeyFor(item);
275
305
  if (!key)
276
306
  return null;
@@ -280,7 +310,47 @@ export class MrdLayoutSection {
280
310
  // Extract parentId from data._links.self.href for RELATED_VIEW path construction
281
311
  const selfHref = (_e = (_d = (_c = (_b = this.data) === null || _b === void 0 ? void 0 : _b._links) === null || _c === void 0 ? void 0 : _c.self) === null || _d === void 0 ? void 0 : _d.href) !== null && _e !== void 0 ? _e : '';
282
312
  const parentId = (_f = selfHref.split('/').filter(Boolean).pop()) !== null && _f !== void 0 ? _f : '';
283
- return (h("div", { class: "mrd-layout-section__related-view", key: `view-${key}` }, showTitle && item.label && h("h3", { class: "mrd-layout-section__related-view-title" }, item.label), h("mrd-table", { "data-view": key, item: item, parentId: parentId, locale: this.locale, onMrdLoadPage: (e) => this.handleViewLoadPage(e, key), onMrdLoadAggregations: (e) => {
313
+ // The API publishes `archetypes` on the VIEW/RELATED_VIEW item itself
314
+ // (sibling of `view`), not inside `view`.
315
+ const docArchetype = resolveArchetype((_g = item.archetypes) !== null && _g !== void 0 ? _g : (_h = item.view) === null || _h === void 0 ? void 0 : _h.archetypes, ARCHETYPE_DOCUMENT);
316
+ return (h("div", { class: "mrd-layout-section__related-view", key: `view-${key}` }, showTitle && item.label && h("h3", { class: "mrd-layout-section__related-view-title" }, item.label), docArchetype
317
+ ? this.renderDocumentContainer(item, key, parentId, docArchetype)
318
+ : this.renderTable(item, key, parentId)));
319
+ }
320
+ /** Document collection view: owns the view-switch + collection actions and
321
+ * swaps between the folder tree and the flat table. Events are re-emitted to
322
+ * the host with the view key, exactly as the raw list/table events were. */
323
+ renderDocumentContainer(item, key, parentId, archetype) {
324
+ return (h("mrd-document-container", { item: item, archetype: archetype, parentId: parentId, viewKey: key, locale: this.locale, onMrdLoadDistinct: (e) => {
325
+ e.stopPropagation();
326
+ this.mrdLoadViewDistinct.emit(Object.assign({ name: key }, e.detail));
327
+ }, onMrdLoadPage: (e) => {
328
+ e.stopPropagation();
329
+ this.mrdLoadViewPage.emit(Object.assign({ name: key }, e.detail));
330
+ }, onMrdLoadAggregations: (e) => {
331
+ var _a;
332
+ e.stopPropagation();
333
+ this.mrdLoadViewAggregations.emit(Object.assign({ name: key, dataClass: (_a = item.dataClass) !== null && _a !== void 0 ? _a : key }, e.detail));
334
+ }, onMrdNavigate: (e) => {
335
+ e.stopPropagation();
336
+ this.mrdNavigate.emit(e.detail);
337
+ }, onMrdAction: (e) => {
338
+ var _a;
339
+ e.stopPropagation();
340
+ this.mrdViewAction.emit(Object.assign({ name: key, dataClass: (_a = item.dataClass) !== null && _a !== void 0 ? _a : key }, e.detail));
341
+ }, onMrdUpdateObject: (e) => {
342
+ e.stopPropagation();
343
+ this.mrdUpdateObject.emit(e.detail);
344
+ }, onMrdUpload: (e) => {
345
+ e.stopPropagation();
346
+ this.mrdViewUpload.emit(Object.assign({ name: key }, e.detail));
347
+ }, onMrdCreateObject: (e) => {
348
+ e.stopPropagation();
349
+ this.mrdCreateObject.emit(Object.assign({ name: key }, e.detail));
350
+ } }));
351
+ }
352
+ renderTable(item, key, parentId) {
353
+ return (h("mrd-table", { "data-view": key, item: item, parentId: parentId, locale: this.locale, onMrdLoadPage: (e) => this.handleViewLoadPage(e, key), onMrdLoadAggregations: (e) => {
284
354
  var _a;
285
355
  e.stopPropagation();
286
356
  this.mrdLoadViewAggregations.emit(Object.assign({ name: key, dataClass: (_a = item.dataClass) !== null && _a !== void 0 ? _a : key }, e.detail));
@@ -301,7 +371,7 @@ export class MrdLayoutSection {
301
371
  parentPath: e.detail.parentPath,
302
372
  basicType: e.detail.basicType,
303
373
  });
304
- } })));
374
+ } }));
305
375
  }
306
376
  renderItem(item) {
307
377
  var _a, _b;
@@ -333,8 +403,23 @@ export class MrdLayoutSection {
333
403
  return null;
334
404
  return (h("div", { class: "mrd-layout-section__modal-backdrop", onClick: () => { this.imagePreviewUrl = null; } }, h("div", { class: "mrd-layout-section__modal", onClick: (e) => e.stopPropagation() }, h("button", { class: "mrd-layout-section__modal-close", onClick: () => { this.imagePreviewUrl = null; } }, "\u2715"), h("img", { class: "mrd-layout-section__modal-image", src: this.imagePreviewUrl, alt: "" }))));
335
405
  }
406
+ /** Single-document view: the record's own type carries commons.document. Renders
407
+ * a recognisable document instead of generic fields, keeping any related views/
408
+ * searches below it. */
409
+ renderDocumentObject(archetype) {
410
+ const related = this.items.filter(it => it.type === ClientLayoutItemType.VIEW ||
411
+ it.type === ClientLayoutItemType.RELATED_VIEW ||
412
+ it.type === ClientLayoutItemType.SEARCH);
413
+ return [
414
+ h("mrd-document-view", { archetype: archetype, data: this.data, locale: this.locale, onMrdNavigate: (e) => { e.stopPropagation(); this.mrdNavigate.emit(e.detail); }, onMrdDownload: (e) => { e.stopPropagation(); this.mrdDownload.emit(e.detail); } }),
415
+ ...related.map(it => this.renderItem(it)),
416
+ ];
417
+ }
336
418
  render() {
337
- return (h(Host, { key: '39d21b05016b901ff73a90dc0c6ef04cc30b4d42' }, h("div", { key: '546d956676d66438930665e97c2ed618fb8d1d4c', class: "mrd-layout-section" }, this.items.map(item => this.renderItem(item))), this.renderImageModal()));
419
+ const docArchetype = resolveArchetype(this.archetypes, ARCHETYPE_DOCUMENT);
420
+ return (h(Host, { key: '6e737354daec0137b6ebe304efcce9990f02739f' }, h("div", { key: '31a73a8a78999793f5dacee5f2da41df5f23156e', class: "mrd-layout-section" }, docArchetype
421
+ ? this.renderDocumentObject(docArchetype)
422
+ : this.items.map(item => this.renderItem(item))), this.renderImageModal()));
338
423
  }
339
424
  static get is() { return "mrd-layout-section"; }
340
425
  static get encapsulation() { return "scoped"; }
@@ -469,6 +554,31 @@ export class MrdLayoutSection {
469
554
  "reflect": false,
470
555
  "attribute": "locale",
471
556
  "defaultValue": "navigator.language"
557
+ },
558
+ "archetypes": {
559
+ "type": "unknown",
560
+ "mutable": false,
561
+ "complexType": {
562
+ "original": "ClientArchetype[]",
563
+ "resolved": "ClientArchetype[]",
564
+ "references": {
565
+ "ClientArchetype": {
566
+ "location": "import",
567
+ "path": "../../types/client-layout",
568
+ "id": "src/types/client-layout.ts::ClientArchetype",
569
+ "referenceLocation": "ClientArchetype"
570
+ }
571
+ }
572
+ },
573
+ "required": false,
574
+ "optional": false,
575
+ "docs": {
576
+ "tags": [],
577
+ "text": "Top-level archetypes on the object dashboard. When it contains commons.document,\nthe record is rendered as a single-document view instead of generic fields."
578
+ },
579
+ "getter": false,
580
+ "setter": false,
581
+ "defaultValue": "[]"
472
582
  }
473
583
  };
474
584
  }
@@ -542,11 +652,11 @@ export class MrdLayoutSection {
542
652
  "composed": true,
543
653
  "docs": {
544
654
  "tags": [],
545
- "text": "Re-emitted from an embedded mrd-table's mrdLoadPage; host fetches the next page and calls setViewPage()."
655
+ "text": "Re-emitted from an embedded mrd-table's or mrd-document-list's mrdLoadPage; host fetches the\nrows and calls setViewPage(). `nodeId` is present for a document-list folder load."
546
656
  },
547
657
  "complexType": {
548
- "original": "{ name: string; page: number; sort: string; path: string; qs: string }",
549
- "resolved": "{ name: string; page: number; sort: string; path: string; qs: string; }",
658
+ "original": "{ name: string; page: number; sort: string; path: string; qs: string; nodeId?: string }",
659
+ "resolved": "{ name: string; page: number; sort: string; path: string; qs: string; nodeId?: string | undefined; }",
550
660
  "references": {}
551
661
  }
552
662
  }, {
@@ -594,6 +704,81 @@ export class MrdLayoutSection {
594
704
  "resolved": "{ name: string; dataClass: string; path: string; qs: string; aggQs: string; }",
595
705
  "references": {}
596
706
  }
707
+ }, {
708
+ "method": "mrdLoadViewDistinct",
709
+ "name": "mrdLoadViewDistinct",
710
+ "bubbles": true,
711
+ "cancelable": true,
712
+ "composed": true,
713
+ "docs": {
714
+ "tags": [],
715
+ "text": "Re-emitted from an embedded mrd-document-list's mrdLoadDistinct; host fetches distinct values and calls setViewDistinct()."
716
+ },
717
+ "complexType": {
718
+ "original": "{ name: string; nodeId: string; distinct: string; path: string; qs: string }",
719
+ "resolved": "{ name: string; nodeId: string; distinct: string; path: string; qs: string; }",
720
+ "references": {}
721
+ }
722
+ }, {
723
+ "method": "mrdUpdateObject",
724
+ "name": "mrdUpdateObject",
725
+ "bubbles": true,
726
+ "cancelable": true,
727
+ "composed": true,
728
+ "docs": {
729
+ "tags": [],
730
+ "text": "Generic \"update an existing object\" request from an embedded document view\n(a document dragged into another folder). Host PATCHes `href` with `values`."
731
+ },
732
+ "complexType": {
733
+ "original": "{ href: string; values: Record<string, unknown> }",
734
+ "resolved": "{ href: string; values: Record<string, unknown>; }",
735
+ "references": {
736
+ "Record": {
737
+ "location": "global",
738
+ "id": "global::Record"
739
+ }
740
+ }
741
+ }
742
+ }, {
743
+ "method": "mrdViewUpload",
744
+ "name": "mrdViewUpload",
745
+ "bubbles": true,
746
+ "cancelable": true,
747
+ "composed": true,
748
+ "docs": {
749
+ "tags": [],
750
+ "text": "An external file was dropped on a document view; host uploads and calls\nsetViewFileReference(name, uri)."
751
+ },
752
+ "complexType": {
753
+ "original": "{ name: string; file: File }",
754
+ "resolved": "{ name: string; file: File; }",
755
+ "references": {
756
+ "File": {
757
+ "location": "global",
758
+ "id": "global::File"
759
+ }
760
+ }
761
+ }
762
+ }, {
763
+ "method": "mrdCreateObject",
764
+ "name": "mrdCreateObject",
765
+ "bubbles": true,
766
+ "cancelable": true,
767
+ "composed": true,
768
+ "docs": {
769
+ "tags": [],
770
+ "text": "Create a new document from an uploaded file; host POSTs `values` to `path`,\nthen calls setViewCreatedObject(name, href) with the new object's href."
771
+ },
772
+ "complexType": {
773
+ "original": "{ name: string; path: string; values: Record<string, unknown> }",
774
+ "resolved": "{ name: string; path: string; values: Record<string, unknown>; }",
775
+ "references": {
776
+ "Record": {
777
+ "location": "global",
778
+ "id": "global::Record"
779
+ }
780
+ }
781
+ }
597
782
  }];
598
783
  }
599
784
  static get methods() {
@@ -631,7 +816,7 @@ export class MrdLayoutSection {
631
816
  },
632
817
  "setViewPage": {
633
818
  "complexType": {
634
- "signature": "(name: string, page: number, rows: any[], totalElements?: number, hasNext?: boolean) => Promise<void>",
819
+ "signature": "(name: string, page: number, rows: any[], totalElements?: number, hasNext?: boolean, nodeId?: string) => Promise<void>",
635
820
  "parameters": [{
636
821
  "name": "name",
637
822
  "type": "string",
@@ -652,6 +837,10 @@ export class MrdLayoutSection {
652
837
  "name": "hasNext",
653
838
  "type": "boolean | undefined",
654
839
  "docs": ""
840
+ }, {
841
+ "name": "nodeId",
842
+ "type": "string | undefined",
843
+ "docs": ""
655
844
  }],
656
845
  "references": {
657
846
  "Promise": {
@@ -662,7 +851,7 @@ export class MrdLayoutSection {
662
851
  "return": "Promise<void>"
663
852
  },
664
853
  "docs": {
665
- "text": "Inject data into an embedded mrd-table for a RELATED_VIEW or VIEW item.\nPass totalElements to update the pagination total (safe to pass on every page).\nPass hasNext (from _links.next presence) so the table can decide whether to emit aggregations.",
854
+ "text": "Inject rows for a VIEW / RELATED_VIEW item.\n- Table view: injects the page into the embedded mrd-table (pass totalElements/hasNext).\n- Document view: pass `nodeId` to route the rows to that folder node in the embedded\n mrd-document-list. Folder loading is just a filtered list load, so it reuses this method.",
666
855
  "tags": []
667
856
  }
668
857
  },
@@ -691,6 +880,91 @@ export class MrdLayoutSection {
691
880
  "tags": []
692
881
  }
693
882
  },
883
+ "setViewDistinct": {
884
+ "complexType": {
885
+ "signature": "(name: string, nodeId: string, values: DistinctValue[]) => Promise<void>",
886
+ "parameters": [{
887
+ "name": "name",
888
+ "type": "string",
889
+ "docs": ""
890
+ }, {
891
+ "name": "nodeId",
892
+ "type": "string",
893
+ "docs": ""
894
+ }, {
895
+ "name": "values",
896
+ "type": "DistinctValue[]",
897
+ "docs": ""
898
+ }],
899
+ "references": {
900
+ "Promise": {
901
+ "location": "global",
902
+ "id": "global::Promise"
903
+ },
904
+ "DistinctValue": {
905
+ "location": "import",
906
+ "path": "../mrd-document-list/mrd-document-list",
907
+ "id": "src/components/mrd-document-list/mrd-document-list.tsx::DistinctValue",
908
+ "referenceLocation": "DistinctValue"
909
+ }
910
+ },
911
+ "return": "Promise<void>"
912
+ },
913
+ "docs": {
914
+ "text": "Inject distinct values into an embedded mrd-document-list for a document view.",
915
+ "tags": []
916
+ }
917
+ },
918
+ "setViewFileReference": {
919
+ "complexType": {
920
+ "signature": "(name: string, uri: string) => Promise<void>",
921
+ "parameters": [{
922
+ "name": "name",
923
+ "type": "string",
924
+ "docs": ""
925
+ }, {
926
+ "name": "uri",
927
+ "type": "string",
928
+ "docs": ""
929
+ }],
930
+ "references": {
931
+ "Promise": {
932
+ "location": "global",
933
+ "id": "global::Promise"
934
+ }
935
+ },
936
+ "return": "Promise<void>"
937
+ },
938
+ "docs": {
939
+ "text": "Inject the uploaded file reference for a dropped file, so the document view\ncan request creation of the new document (see mrdViewUpload).",
940
+ "tags": []
941
+ }
942
+ },
943
+ "setViewCreatedObject": {
944
+ "complexType": {
945
+ "signature": "(name: string, href: string) => Promise<void>",
946
+ "parameters": [{
947
+ "name": "name",
948
+ "type": "string",
949
+ "docs": ""
950
+ }, {
951
+ "name": "href",
952
+ "type": "string",
953
+ "docs": ""
954
+ }],
955
+ "references": {
956
+ "Promise": {
957
+ "location": "global",
958
+ "id": "global::Promise"
959
+ }
960
+ },
961
+ "return": "Promise<void>"
962
+ },
963
+ "docs": {
964
+ "text": "Inject the created document's href after a file-drop create, so the\noptimistic row becomes navigable (see mrdCreateObject).",
965
+ "tags": []
966
+ }
967
+ },
694
968
  "setImagePreview": {
695
969
  "complexType": {
696
970
  "signature": "(fieldName: string, url: string) => Promise<void>",
@@ -250,13 +250,12 @@
250
250
  }
251
251
 
252
252
  .mrd-layout-section__group-title {
253
- font-size: var(--mrd-font-size-sm);
253
+ font-size: var(--mrd-font-size-xs);
254
254
  font-weight: var(--mrd-font-weight-semibold);
255
255
  color: var(--mrd-color-neutral-500);
256
256
  margin: 0 0 var(--mrd-space-2) 0;
257
257
  padding-bottom: 0;
258
- text-transform: uppercase;
259
- letter-spacing: 0.05em;
258
+ letter-spacing: 0.01em;
260
259
  }
261
260
 
262
261
  .mrd-layout-section__related-view {
@@ -28,7 +28,7 @@ export class MrdLongtextField {
28
28
  }
29
29
  render() {
30
30
  const hasError = !!this.error;
31
- return (h(Host, { key: '10d998b80f54cf7b10be26bf451d808c78579e69' }, h("div", { key: 'af45fe94a41f668bf6ddca670b42e065ee83ef23', class: "mrd-longtext-field" }, this.label && (h("label", { key: '31a08490d695ac9f4bbe5dff6a1ae3bb2a94337d', class: `mrd-longtext-field__label${this.required ? ' mrd-longtext-field__label--required' : ''}` }, this.label)), this.disabled ? (h("pre", { class: "mrd-longtext-field__content" }, this.value)) : (h("textarea", { class: `mrd-longtext-field__input${hasError ? ' mrd-longtext-field__input--error' : ''}`, name: this.name, placeholder: this.placeholder, required: this.required, rows: 10, onInput: this.handleInput, onBlur: this.handleBlur }, this.value)), hasError && h("span", { key: '7f133e72a882a8aaf33245445829754da1e6377b', class: "mrd-longtext-field__error" }, this.error))));
31
+ return (h(Host, { key: 'f00f81944748f8f09e22d44befe5e288456b7cc8' }, h("div", { key: '7b0ae9cf5b6b684cddb648fe4db6005494322535', class: "mrd-longtext-field" }, this.label && (h("label", { key: '3fc6a8710d0e98fe685c45d214a88ae1b0947973', class: `mrd-longtext-field__label${this.required ? ' mrd-longtext-field__label--required' : ''}` }, this.label)), this.disabled ? (h("pre", { class: "mrd-longtext-field__content" }, this.value)) : (h("textarea", { class: `mrd-longtext-field__input${hasError ? ' mrd-longtext-field__input--error' : ''}`, name: this.name, placeholder: this.placeholder, required: this.required, rows: 10, onInput: this.handleInput, onBlur: this.handleBlur }, this.value)), hasError && h("span", { key: 'e96f1dbc6c00a1602f4ce3c97d514a229aeb7cb7', class: "mrd-longtext-field__error" }, this.error))));
32
32
  }
33
33
  static get is() { return "mrd-longtext-field"; }
34
34
  static get encapsulation() { return "scoped"; }
@@ -69,7 +69,7 @@ export class MrdNumberField {
69
69
  const hasError = !!this.error;
70
70
  const suffix = this.dataType === ClientLayoutItemFieldDataType.PERCENTAGE ? '%' :
71
71
  this.dataType === ClientLayoutItemFieldDataType.DECIMAL ? '' : '';
72
- return (h(Host, { key: '195beed4d6453597320b79654feaabe8f742eff2' }, h("div", { key: 'c641d7a4d27ba28dd34acda98d38f245945d20bb', class: "mrd-number-field" }, this.label && (h("label", { key: '2a5f6eb48889a3ab0aa76d6b2ca5d59b20625bb2', class: `mrd-number-field__label${this.required ? ' mrd-number-field__label--required' : ''}` }, this.label)), h("div", { key: 'a844b89e6a278629a8aefa4ac72e5e18e5904cab', class: "mrd-number-field__input-wrapper" }, h("input", { key: '1ce9c3d67b458601a0de95b3b8478ef05df73069', class: `mrd-number-field__input${hasError ? ' mrd-number-field__input--error' : ''}`, type: "text", inputMode: "decimal", name: this.name, value: this.displayValue, placeholder: this.placeholder || (suffix ? `0${suffix}` : '0'), required: this.required, disabled: this.disabled, onInput: this.handleInput, onBlur: this.handleBlur, onFocus: this.handleFocus })), hasError && h("span", { key: '4226614a65a8d27543d1287e2c1f61f67c427e63', class: "mrd-number-field__error" }, this.error))));
72
+ return (h(Host, { key: 'b034a3cc8d841641c0ec167e138904586b044121' }, h("div", { key: '7379bfadb8bd0c4e0a945a37013053a4e22477ab', class: "mrd-number-field" }, this.label && (h("label", { key: '5518d40b7158e17704633c2b95ac7e3efc0c5568', class: `mrd-number-field__label${this.required ? ' mrd-number-field__label--required' : ''}` }, this.label)), h("div", { key: '38ad9f3c945d66c23bd77c743306e916eaefed7f', class: "mrd-number-field__input-wrapper" }, h("input", { key: 'ac8b4bc1ea4431cc9306664522ebfda21760ae83', class: `mrd-number-field__input${hasError ? ' mrd-number-field__input--error' : ''}`, type: "text", inputMode: "decimal", name: this.name, value: this.displayValue, placeholder: this.placeholder || (suffix ? `0${suffix}` : '0'), required: this.required, disabled: this.disabled, onInput: this.handleInput, onBlur: this.handleBlur, onFocus: this.handleFocus })), hasError && h("span", { key: '09f5a58b769c81acdf4bdd48f9325934c4bb875d', class: "mrd-number-field__error" }, this.error))));
73
73
  }
74
74
  static get is() { return "mrd-number-field"; }
75
75
  static get encapsulation() { return "scoped"; }
@@ -28,9 +28,9 @@ export class MrdSecretField {
28
28
  }
29
29
  render() {
30
30
  const hasError = !!this.error;
31
- return (h(Host, { key: '08f1aa9d8ab9f4e41abb6d3286e5e383427a5409' }, h("div", { key: 'fabe38aa130e211cea81f2c2f227bc15ad3ebf7d', class: "mrd-secret-field" }, this.label && (h("label", { key: '69af8844eff8ce84daa622635c79130fb491eb0b', class: `mrd-secret-field__label${this.required ? ' mrd-secret-field__label--required' : ''}` }, this.label)), this.disabled
31
+ return (h(Host, { key: 'c850ec5bc5967ca0aefca7d7cb65ecae121a9dc1' }, h("div", { key: '3249ffbc441422af054a20806dd8dfce954a8ffc', class: "mrd-secret-field" }, this.label && (h("label", { key: '0b4a86da9cafad32f153af1bc5487a4e9b941e2f', class: `mrd-secret-field__label${this.required ? ' mrd-secret-field__label--required' : ''}` }, this.label)), this.disabled
32
32
  ? (h("span", { class: "mrd-secret-field__masked", "aria-label": this.label }, this.value ? '••••••••' : ''))
33
- : (h("input", { class: `mrd-secret-field__input${hasError ? ' mrd-secret-field__input--error' : ''}`, type: "password", name: this.name, value: this.value, placeholder: this.placeholder, required: this.required, autocomplete: "new-password", onInput: this.handleInput, onBlur: this.handleBlur })), hasError && h("span", { key: 'e602004f0bb10916d1015e3c2b003523a292997c', class: "mrd-secret-field__error" }, this.error))));
33
+ : (h("input", { class: `mrd-secret-field__input${hasError ? ' mrd-secret-field__input--error' : ''}`, type: "password", name: this.name, value: this.value, placeholder: this.placeholder, required: this.required, autocomplete: "new-password", onInput: this.handleInput, onBlur: this.handleBlur })), hasError && h("span", { key: 'b0d0105f3d43d2e214f070b24e745dbce0e33977', class: "mrd-secret-field__error" }, this.error))));
34
34
  }
35
35
  static get is() { return "mrd-secret-field"; }
36
36
  static get encapsulation() { return "scoped"; }
@@ -28,7 +28,7 @@ export class MrdTextField {
28
28
  }
29
29
  render() {
30
30
  const hasError = !!this.error;
31
- return (h(Host, { key: 'fd4e1f389cb452ab80a1e1c7295d884ca935999e' }, h("div", { key: '7b7bde7a18fcd9b8d5779daab88ddabb45dd8692', class: "mrd-text-field" }, this.label && (h("label", { key: '8e2ad4053473cfad4eae4c4634b863ac5ef32fea', class: `mrd-text-field__label${this.required ? ' mrd-text-field__label--required' : ''}` }, this.label)), h("input", { key: 'd32712a6dc2aee4691bc4a580d5ca2ad81e0ff9f', class: `mrd-text-field__input${hasError ? ' mrd-text-field__input--error' : ''}`, type: "text", name: this.name, value: this.value, placeholder: this.placeholder, required: this.required, disabled: this.disabled, onInput: this.handleInput, onBlur: this.handleBlur }), hasError && h("span", { key: '31585dbf82020c81834e1eeada5cd9907a5ead56', class: "mrd-text-field__error" }, this.error))));
31
+ return (h(Host, { key: 'e9252b251faf98ab190e643b97c13fa32d12ef22' }, h("div", { key: '37f4259a111c293f2fe12f321f08c00c25e77feb', class: "mrd-text-field" }, this.label && (h("label", { key: 'c59e0346fb71a765ea38629b03c06341567ed210', class: `mrd-text-field__label${this.required ? ' mrd-text-field__label--required' : ''}` }, this.label)), h("input", { key: 'dc09953a672472348719f29904d900966d945843', class: `mrd-text-field__input${hasError ? ' mrd-text-field__input--error' : ''}`, type: "text", name: this.name, value: this.value, placeholder: this.placeholder, required: this.required, disabled: this.disabled, onInput: this.handleInput, onBlur: this.handleBlur }), hasError && h("span", { key: '037653857a372854a16b28ebf8994b23e3e0d696', class: "mrd-text-field__error" }, this.error))));
32
32
  }
33
33
  static get is() { return "mrd-text-field"; }
34
34
  static get encapsulation() { return "scoped"; }
@@ -66,7 +66,7 @@ export class MrdTextareaField {
66
66
  }
67
67
  }
68
68
  render() {
69
- return (h(Host, { key: 'e1fd819c598f01e3986946357ec18d608f2c7adc' }, h("div", { key: '20c28e54e61429655b2d4f297bd84e183ad7e971', class: "mrd-textarea-field" }, this.label && (h("label", { key: 'fa46a20badc35c931563600f24a32e0a8c8c07ad', class: `mrd-textarea-field__label${this.required ? ' mrd-textarea-field__label--required' : ''}` }, this.label)), h("div", { key: 'ee928eca0a1b85401b346b7fae8adbe9214a7664', class: `mrd-textarea-field__container${this.error ? ' mrd-textarea-field__container--error' : ''}` }, h("div", { key: '89b00f3c526623c47f0aff7ad862f70dfdc2fe15', class: "mrd-textarea-field__editor" })), this.error && h("span", { key: '458cf8fddee36ddbc384ce4d25765e5aacd3c9d5', class: "mrd-textarea-field__error" }, this.error))));
69
+ return (h(Host, { key: 'fe7824c81e082c3f2c1cf18c11dde20cb1f40f2c' }, h("div", { key: 'adf394a7e146d16bc79006873a209b11d88b2e17', class: "mrd-textarea-field" }, this.label && (h("label", { key: '1b0dd2b4cf26c55a0af05c67a3178edc0c9d56c4', class: `mrd-textarea-field__label${this.required ? ' mrd-textarea-field__label--required' : ''}` }, this.label)), h("div", { key: '7c8fe88b222af0beed08db492aa9f6d890e0dc5b', class: `mrd-textarea-field__container${this.error ? ' mrd-textarea-field__container--error' : ''}` }, h("div", { key: '295968283e94812cb04660117c5bdeaf3647469c', class: "mrd-textarea-field__editor" })), this.error && h("span", { key: '5b5ab61053ab0792d4c249de04bd1d13b51469bf', class: "mrd-textarea-field__error" }, this.error))));
70
70
  }
71
71
  static get is() { return "mrd-textarea-field"; }
72
72
  static get encapsulation() { return "scoped"; }
@@ -27,7 +27,7 @@ export class MrdTimeField {
27
27
  }
28
28
  render() {
29
29
  const hasError = !!this.error;
30
- return (h(Host, { key: 'c507996709437d8982f9175b286e25598997002d' }, h("div", { key: 'd5f1b7f14d26cae8298cd40491898b39044158f8', class: "mrd-time-field" }, this.label && (h("label", { key: '10976e18df09240e00b045314c4ddd3845d4bfdc', class: `mrd-time-field__label${this.required ? ' mrd-time-field__label--required' : ''}` }, this.label)), h("input", { key: 'bc557333f107a371a7005f9b56dd0395190e63d7', class: `mrd-time-field__input${hasError ? ' mrd-time-field__input--error' : ''}`, type: "time", name: this.name, value: this.value, required: this.required, disabled: this.disabled, onChange: this.handleChange, onBlur: this.handleBlur }), hasError && h("span", { key: 'b5a09c2aa063fa9e2fc3aba411e86b57d879c408', class: "mrd-time-field__error" }, this.error))));
30
+ return (h(Host, { key: '579219a478e31325b5a676465807c1d936724a2b' }, h("div", { key: '51b25f6e083a29989505c0ad79edbcd3b0060736', class: "mrd-time-field" }, this.label && (h("label", { key: '67d98bebb8803deea2d2a4a63f36706789ccd8c7', class: `mrd-time-field__label${this.required ? ' mrd-time-field__label--required' : ''}` }, this.label)), h("input", { key: '734741e0db1bdd5886fef37bba3b2f8d7200a0ab', class: `mrd-time-field__input${hasError ? ' mrd-time-field__input--error' : ''}`, type: "time", name: this.name, value: this.value, required: this.required, disabled: this.disabled, onChange: this.handleChange, onBlur: this.handleBlur }), hasError && h("span", { key: '0dbd168d14966dc56a77c97cd8fd8f9b208a4bf5', class: "mrd-time-field__error" }, this.error))));
31
31
  }
32
32
  static get is() { return "mrd-time-field"; }
33
33
  static get encapsulation() { return "scoped"; }
@@ -379,17 +379,21 @@ async function renderSection(index) {
379
379
  section.items = layout.items;
380
380
  section.data = _dashboardRecord ?? { _links: _dashboardData._links ?? {} };
381
381
  section.locale = _locale;
382
+ // Dashboard-level archetypes describe the object itself → single-document view.
383
+ // Only apply to the main object layout, not tab-page (related) layouts.
384
+ section.archetypes = (!layout.tabPage && _dashboardData.archetypes) ? _dashboardData.archetypes : [];
382
385
 
383
386
  section.addEventListener('mrdLoadViewPage', async (e) => {
384
387
  if (generation !== _sectionGeneration) return;
385
- const { name, page, path, qs } = e.detail;
388
+ const { name, page, path, qs, nodeId } = e.detail;
386
389
  logEvent('mrdLoadViewPage', e.detail);
387
390
  try {
388
391
  const url = `${_baseHref}${path}${qs ? '?' + qs : ''}`;
389
392
  const result = await apiFetchPage(authGetToken(), url, page);
390
393
  const rows = Object.values(result._embedded ?? {})[0] ?? [];
391
394
  const total = result.page?.totalElements;
392
- await section.setViewPage(name, page, rows, total);
395
+ // nodeId present document-list folder load; routed to the tree node.
396
+ await section.setViewPage(name, page, rows, total, undefined, nodeId);
393
397
  } catch (err) {
394
398
  console.error('[mrdLoadViewPage] mislukt', name, err);
395
399
  }
@@ -408,6 +412,19 @@ async function renderSection(index) {
408
412
  }
409
413
  });
410
414
 
415
+ section.addEventListener('mrdLoadViewDistinct', async (e) => {
416
+ if (generation !== _sectionGeneration) return;
417
+ const { name, nodeId, path, qs } = e.detail;
418
+ logEvent('mrdLoadViewDistinct', e.detail);
419
+ try {
420
+ const url = `${_baseHref}${path}${qs ? '?' + qs : ''}`;
421
+ const result = await apiRequest('GET', url, authGetToken());
422
+ if (result.ok) await section.setViewDistinct(name, nodeId, result.body?.values ?? []);
423
+ } catch (err) {
424
+ console.error('[mrdLoadViewDistinct] mislukt', name, err);
425
+ }
426
+ });
427
+
411
428
  section.addEventListener('mrdViewAction', async (e) => {
412
429
  logEvent('mrdViewAction', e.detail);
413
430
  const { action, dataClass } = e.detail;
@@ -423,6 +440,53 @@ async function renderSection(index) {
423
440
  section.addEventListener('mrdDownload', (e) => logEvent('mrdDownload', e.detail));
424
441
  section.addEventListener('mrdSearch', (e) => logEvent('mrdSearch', e.detail));
425
442
 
443
+ // Generic in-place update (e.g. a document dragged into another folder).
444
+ // Fire-and-forget PATCH; the component already updated its tree optimistically.
445
+ section.addEventListener('mrdUpdateObject', async (e) => {
446
+ if (generation !== _sectionGeneration) return;
447
+ const { href, values } = e.detail;
448
+ logEvent('mrdUpdateObject', e.detail);
449
+ try {
450
+ const result = await apiRequest('PATCH', href, authGetToken(), values);
451
+ if (!result.ok) console.error('[mrdUpdateObject] mislukt', result.status, result.body);
452
+ } catch (err) {
453
+ console.error('[mrdUpdateObject] mislukt', href, err);
454
+ }
455
+ });
456
+
457
+ // External file dropped on a folder: upload it, then hand the reference back to
458
+ // the component (same flow as mrd-form's mrdUpload → setFieldValue).
459
+ section.addEventListener('mrdViewUpload', async (e) => {
460
+ if (generation !== _sectionGeneration) return;
461
+ const { name, file } = e.detail;
462
+ logEvent('mrdViewUpload', { name, file: file?.name });
463
+ try {
464
+ const uri = await apiUploadFile(authGetToken(), _selectedTenant, file);
465
+ await section.setViewFileReference(name, uri);
466
+ } catch (err) {
467
+ console.error('[mrdViewUpload] upload mislukt', name, err);
468
+ }
469
+ });
470
+
471
+ // Create a new document from the uploaded file. POST; a 400 would be where the
472
+ // real host opens the create-form fallback (out of scope for the dev page).
473
+ section.addEventListener('mrdCreateObject', async (e) => {
474
+ if (generation !== _sectionGeneration) return;
475
+ const { name, path, values } = e.detail;
476
+ logEvent('mrdCreateObject', e.detail);
477
+ try {
478
+ const result = await apiRequest('POST', `${_baseHref}${path}`, authGetToken(), values);
479
+ if (result.ok) {
480
+ const href = result.body?._links?.self?.href;
481
+ if (href) await section.setViewCreatedObject(name, href);
482
+ } else {
483
+ console.error('[mrdCreateObject] mislukt', result.status, result.body);
484
+ }
485
+ } catch (err) {
486
+ console.error('[mrdCreateObject] mislukt', path, err);
487
+ }
488
+ });
489
+
426
490
  container.appendChild(section);
427
491
  }
428
492
 
@@ -62,3 +62,13 @@ export var ClientLayoutItemRelationEditBehavior;
62
62
  ClientLayoutItemRelationEditBehavior["DROPDOWN"] = "DROPDOWN";
63
63
  ClientLayoutItemRelationEditBehavior["CHECKBOX"] = "CHECKBOX";
64
64
  })(ClientLayoutItemRelationEditBehavior || (ClientLayoutItemRelationEditBehavior = {}));
65
+ /** Well-known archetype ids the client renders specially. */
66
+ export const ARCHETYPE_DOCUMENT = 'commons.document';
67
+ /**
68
+ * Find a binding for `archetypeId` in a published `archetypes` list.
69
+ * Returns `undefined` when the archetype is absent — callers fall back to the
70
+ * generic table/field rendering.
71
+ */
72
+ export function resolveArchetype(archetypes, archetypeId) {
73
+ return (archetypes !== null && archetypes !== void 0 ? archetypes : []).find(a => a.archetype === archetypeId);
74
+ }