@mmlogic/components 0.5.12 → 0.5.13

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 (35) hide show
  1. package/dist/cjs/{cell-renderer-pwUGEDql.js → cell-renderer-BBebjBVz.js} +8 -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_25.cjs.entry.js +67 -20
  5. package/dist/cjs/mrd-merge-view.cjs.entry.js +1 -1
  6. package/dist/collection/components/documents/mrd-document-container/mrd-document-container.js +30 -4
  7. package/dist/collection/components/documents/mrd-document-list/mrd-document-list.js +55 -6
  8. package/dist/collection/components/layout/mrd-layout-section/mrd-layout-section.js +27 -3
  9. package/dist/collection/components/table/mrd-table/mrd-table.js +26 -2
  10. package/dist/collection/components/table/mrd-table/table-parts.js +9 -5
  11. package/dist/collection/dev/app.js +24 -0
  12. package/dist/collection/utils/i18n.js +8 -0
  13. package/dist/components/i18n.js +1 -1
  14. package/dist/components/mrd-document-container2.js +1 -1
  15. package/dist/components/mrd-document-list2.js +1 -1
  16. package/dist/components/mrd-layout-section.js +1 -1
  17. package/dist/components/mrd-table2.js +1 -1
  18. package/dist/esm/{cell-renderer-B8rJpnq8.js → cell-renderer-CC8-MtvQ.js} +8 -0
  19. package/dist/esm/loader.js +1 -1
  20. package/dist/esm/mosterdcomponents.js +1 -1
  21. package/dist/esm/mrd-boolean-field_25.entry.js +67 -20
  22. package/dist/esm/mrd-merge-view.entry.js +1 -1
  23. package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
  24. package/dist/mosterdcomponents/p-07b148b2.entry.js +3 -0
  25. package/dist/mosterdcomponents/p-D5ZPfX3-.js +1 -0
  26. package/dist/mosterdcomponents/{p-e540de6a.entry.js → p-a7e8f6a3.entry.js} +1 -1
  27. package/dist/types/components/documents/mrd-document-container/mrd-document-container.d.ts +4 -0
  28. package/dist/types/components/documents/mrd-document-list/mrd-document-list.d.ts +6 -1
  29. package/dist/types/components/layout/mrd-layout-section/mrd-layout-section.d.ts +4 -0
  30. package/dist/types/components/table/mrd-table/mrd-table.d.ts +4 -0
  31. package/dist/types/components/table/mrd-table/table-parts.d.ts +3 -0
  32. package/dist/types/components.d.ts +45 -1
  33. package/package.json +1 -1
  34. package/dist/mosterdcomponents/p-eb322d5c.entry.js +0 -3
  35. package/dist/mosterdcomponents/p-rTM1tU_M.js +0 -1
@@ -1,5 +1,5 @@
1
1
  import { r as registerInstance, c as createEvent, h, H as Host, g as getElement, w as writeTask } from './index-CDiBvvJU.js';
2
- import { t, p as parseLocalizedNumber, f as formatNumber, a as formatDate, b as formatDateTime, c as formatCurrency, C as CellRenderer, d as formatPercentage } from './cell-renderer-B8rJpnq8.js';
2
+ import { t, p as parseLocalizedNumber, f as formatNumber, a as formatDate, b as formatDateTime, c as formatCurrency, C as CellRenderer, d as formatPercentage } from './cell-renderer-CC8-MtvQ.js';
3
3
  import { b as ClientLayoutItemFieldDataType, e as ClientLayoutNavigateBehaviour, a as ClientLayoutItemType, c as ClientLayoutItemRelationDisplayType, d as ClientLayoutItemRelationEditBehavior, r as resolveArchetype, A as ARCHETYPE_DOCUMENT, h as ARCHETYPE_INVOICE_LINE, f as ARCHETYPE_INVOICE, g as ARCHETYPE_EMAIL } from './client-layout-Bc42CfJB.js';
4
4
 
5
5
  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)}`;
@@ -361,6 +361,10 @@ const MrdDocumentContainer = class {
361
361
  * on top, Finder-style. The table manages its own height. */
362
362
  this.height = 460;
363
363
  this.locale = navigator.language;
364
+ /** When true, this dashboard is read-only: New folder and Upload are disabled
365
+ * (with a tooltip explaining why) and the embedded table/list get it passed
366
+ * through so their own create/upload/drag-drop paths are disabled too. */
367
+ this.readOnly = false;
364
368
  /** Active body: folder tree or flat table. */
365
369
  this.mode = 'tree';
366
370
  /** Whether the folder tree currently has a valid target for "New folder". */
@@ -375,6 +379,8 @@ const MrdDocumentContainer = class {
375
379
  };
376
380
  this.pickFile = () => {
377
381
  var _a;
382
+ if (this.readOnly)
383
+ return;
378
384
  (_a = this.fileInputEl) === null || _a === void 0 ? void 0 : _a.click();
379
385
  };
380
386
  /** One file per upload, matching the drop handler. Reset the input afterwards
@@ -411,11 +417,11 @@ const MrdDocumentContainer = class {
411
417
  }
412
418
  // ── Toolbar ────────────────────────────────────────────────────────────────
413
419
  renderToolbar() {
414
- return (h("div", { class: "mrd-document-container__toolbar" }, this.mode === 'tree' && (h("button", { type: "button", class: "mrd-document-container__action", disabled: !this.canCreate, onClick: this.createFolder }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" }), h("path", { d: "M12 11v4M10 13h4" })), t('new_folder', this.locale))), this.mode === 'tree' && (h("button", { type: "button", class: "mrd-document-container__action", disabled: !this.canCreate, title: this.targetLabel ? `${t('doc_upload_to', this.locale)} ${this.targetLabel}` : undefined, onClick: this.pickFile }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }), h("path", { d: "M12 3v13M7 8l5-5 5 5" })), t('doc_upload', this.locale))), h("input", { type: "file", class: "mrd-document-container__file-input", ref: el => (this.fileInputEl = el), onChange: this.onFilePicked }), h("div", { class: "mrd-document-container__seg", role: "group", "aria-label": t('doc_view_switch', this.locale) }, h("button", { class: "mrd-document-container__seg-btn", "aria-pressed": String(this.mode === 'tree'), title: t('doc_view_tree', this.locale), "aria-label": t('doc_view_tree', this.locale), onClick: () => this.setMode('tree') }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M3 5h6M3 12h9M3 19h6" }), h("circle", { cx: "18", cy: "5", r: "1.6" }), h("circle", { cx: "18", cy: "19", r: "1.6" }), h("path", { d: "M16 12h4" }))), h("button", { class: "mrd-document-container__seg-btn", "aria-pressed": String(this.mode === 'list'), title: t('doc_view_list', this.locale), "aria-label": t('doc_view_list', this.locale), onClick: () => this.setMode('list') }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01" }))))));
420
+ return (h("div", { class: "mrd-document-container__toolbar" }, this.mode === 'tree' && (h("button", { type: "button", class: "mrd-document-container__action", disabled: this.readOnly || !this.canCreate, title: this.readOnly ? t('readonly_access', this.locale) : undefined, onClick: this.createFolder }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M3 7a2 2 0 0 1 2-2h4l2 2h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" }), h("path", { d: "M12 11v4M10 13h4" })), t('new_folder', this.locale))), this.mode === 'tree' && (h("button", { type: "button", class: "mrd-document-container__action", disabled: this.readOnly || !this.canCreate, title: this.readOnly ? t('readonly_access', this.locale) : (this.targetLabel ? `${t('doc_upload_to', this.locale)} ${this.targetLabel}` : undefined), onClick: this.pickFile }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }), h("path", { d: "M12 3v13M7 8l5-5 5 5" })), t('doc_upload', this.locale))), h("input", { type: "file", class: "mrd-document-container__file-input", ref: el => (this.fileInputEl = el), onChange: this.onFilePicked }), h("div", { class: "mrd-document-container__seg", role: "group", "aria-label": t('doc_view_switch', this.locale) }, h("button", { class: "mrd-document-container__seg-btn", "aria-pressed": String(this.mode === 'tree'), title: t('doc_view_tree', this.locale), "aria-label": t('doc_view_tree', this.locale), onClick: () => this.setMode('tree') }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M3 5h6M3 12h9M3 19h6" }), h("circle", { cx: "18", cy: "5", r: "1.6" }), h("circle", { cx: "18", cy: "19", r: "1.6" }), h("path", { d: "M16 12h4" }))), h("button", { class: "mrd-document-container__seg-btn", "aria-pressed": String(this.mode === 'list'), title: t('doc_view_list', this.locale), "aria-label": t('doc_view_list', this.locale), onClick: () => this.setMode('list') }, h("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", "aria-hidden": "true" }, h("path", { d: "M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01" }))))));
415
421
  }
416
422
  // ── Bodies ───────────────────────────────────────────────────────────────
417
423
  renderTree() {
418
- return (h("mrd-document-list", { "data-doclist": this.viewKey, ref: el => (this.listEl = el), item: this.item, archetype: this.archetype, parentId: this.parentId, containerHref: this.containerHref, locale: this.locale, onMrdLoadDistinct: (e) => {
424
+ return (h("mrd-document-list", { "data-doclist": this.viewKey, ref: el => (this.listEl = el), item: this.item, archetype: this.archetype, parentId: this.parentId, containerHref: this.containerHref, locale: this.locale, readOnly: this.readOnly, onMrdLoadDistinct: (e) => {
419
425
  e.stopPropagation();
420
426
  this.mrdLoadDistinct.emit(e.detail);
421
427
  }, onMrdLoadPage: (e) => {
@@ -442,7 +448,7 @@ const MrdDocumentContainer = class {
442
448
  } }));
443
449
  }
444
450
  renderList() {
445
- return (h("mrd-table", { "data-view": this.viewKey, ref: el => (this.tableEl = el), item: this.item, parentId: this.parentId, locale: this.locale, onMrdLoadPage: (e) => {
451
+ return (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) => {
446
452
  e.stopPropagation();
447
453
  this.mrdLoadPage.emit(e.detail);
448
454
  }, onMrdLoadAggregations: (e) => {
@@ -466,7 +472,7 @@ const MrdDocumentContainer = class {
466
472
  }
467
473
  render() {
468
474
  const treeMode = this.mode === 'tree';
469
- return (h(Host, { key: 'ae948e2458d9087179e850b527802c489067d93f' }, this.renderToolbar(), h("div", { key: 'a04e1a78413aa794d0bda551aeb9c6245f1aafa2', class: {
475
+ return (h(Host, { key: '6792d49f08dd19f6c51e4b656df06bbd8bc14f3e' }, this.renderToolbar(), h("div", { key: '702f4c288f8c40bd2c5999beb392b9dfd022b0bc', class: {
470
476
  'mrd-document-container__body': true,
471
477
  'mrd-document-container__body--tree': treeMode,
472
478
  }, style: treeMode ? { height: `${this.height}px`, overflowY: 'auto' } : {} }, treeMode ? this.renderTree() : this.renderList())));
@@ -733,6 +739,11 @@ const MrdDocumentList = class {
733
739
  * accepts file drops and folder creation. */
734
740
  this.containerHref = '';
735
741
  this.locale = navigator.language;
742
+ /** When true, folder creation, file upload (button and drag-drop) and moving a
743
+ * document between folders are all disabled — a viewer-role user can browse
744
+ * but not mutate anything. Drives mrdCanCreate(false) so the host toolbar's
745
+ * New folder / Upload buttons stay disabled too. */
746
+ this.readOnly = false;
736
747
  this.containers = [];
737
748
  this.rootLoading = true;
738
749
  /** True when the single-container level is collapsed away (dossier context). */
@@ -775,6 +786,8 @@ const MrdDocumentList = class {
775
786
  /** The optimistic document row awaiting its self href from the create POST. */
776
787
  this.lastOptimisticDoc = null;
777
788
  this.startCreateFolder = () => {
789
+ if (this.readOnly)
790
+ return;
778
791
  const resolved = this.resolveTarget();
779
792
  if (!resolved || this.pendingNode)
780
793
  return;
@@ -814,6 +827,10 @@ const MrdDocumentList = class {
814
827
  // ── Drag & drop: move a document into another folder / container ────────────
815
828
  this.onDocDragStart = (e, doc, node) => {
816
829
  var _a, _b, _c;
830
+ if (this.readOnly) {
831
+ e.preventDefault();
832
+ return;
833
+ }
817
834
  this.dragDoc = doc;
818
835
  this.dragFromId = node.id;
819
836
  if (e.dataTransfer) {
@@ -833,6 +850,11 @@ const MrdDocumentList = class {
833
850
  * root drop-zone; a different node is highlighted (its own folder = no-op). */
834
851
  this.onNodeDragOver = (e, node) => {
835
852
  const file = this.isFileDrag(e);
853
+ if (this.readOnly) {
854
+ if (file)
855
+ e.preventDefault(); // swallow so the browser doesn't navigate to the dropped file
856
+ return;
857
+ }
836
858
  if (!this.dragDoc && !file)
837
859
  return;
838
860
  e.preventDefault();
@@ -848,6 +870,10 @@ const MrdDocumentList = class {
848
870
  this.dropTargetId = null;
849
871
  };
850
872
  this.onNodeDrop = (e, node, container) => {
873
+ if (this.readOnly) {
874
+ e.preventDefault();
875
+ return;
876
+ }
851
877
  if (this.isFileDrag(e)) {
852
878
  e.preventDefault();
853
879
  e.stopPropagation();
@@ -866,6 +892,11 @@ const MrdDocumentList = class {
866
892
  if (!this.singleContainer)
867
893
  return;
868
894
  const file = this.isFileDrag(e);
895
+ if (this.readOnly) {
896
+ if (file)
897
+ e.preventDefault(); // swallow so the browser doesn't navigate to the dropped file
898
+ return;
899
+ }
869
900
  if (!this.dragDoc && !file)
870
901
  return;
871
902
  e.preventDefault();
@@ -883,6 +914,10 @@ const MrdDocumentList = class {
883
914
  };
884
915
  this.onRootDrop = (e) => {
885
916
  this.rootDropActive = false;
917
+ if (this.readOnly) {
918
+ e.preventDefault();
919
+ return;
920
+ }
886
921
  if (!this.singleContainer)
887
922
  return;
888
923
  const only = this.containers[0];
@@ -1153,10 +1188,10 @@ const MrdDocumentList = class {
1153
1188
  return null;
1154
1189
  }
1155
1190
  get canCreateFolder() {
1156
- return !this.pendingNode && this.resolveTarget() !== null;
1191
+ return !this.readOnly && !this.pendingNode && this.resolveTarget() !== null;
1157
1192
  }
1158
1193
  /** Start creating a folder under the current target. Called by the host toolbar
1159
- * (mrd-document-container). No-op when there is no valid target. */
1194
+ * (mrd-document-container). No-op when there is no valid target, or read-only. */
1160
1195
  async createFolder() {
1161
1196
  this.startCreateFolder();
1162
1197
  }
@@ -1242,7 +1277,7 @@ const MrdDocumentList = class {
1242
1277
  * (mrd-document-container). No-op without a target, or while another upload
1243
1278
  * is still awaiting its setFileReference. */
1244
1279
  async uploadFile(file) {
1245
- if (!file || this.pendingUpload)
1280
+ if (this.readOnly || !file || this.pendingUpload)
1246
1281
  return;
1247
1282
  const resolved = this.resolveTarget();
1248
1283
  if (!resolved)
@@ -1383,7 +1418,7 @@ const MrdDocumentList = class {
1383
1418
  body = renderLoadingRow(ctx, 0);
1384
1419
  }
1385
1420
  else if (this.containers.length === 0) {
1386
- body = h("div", { key: '63604a99fc62d9108f61b8efc126c0cd3e8fc5ed', class: "mrd-document-list__empty" }, t('no_results', this.locale));
1421
+ body = h("div", { key: '5d473ec3a894361325a71deb14e7b52d0abc5f06', class: "mrd-document-list__empty" }, t('no_results', this.locale));
1387
1422
  }
1388
1423
  else if (this.singleContainer) {
1389
1424
  // Dossier context: render the single container's folder tree at the root.
@@ -1401,7 +1436,7 @@ const MrdDocumentList = class {
1401
1436
  else {
1402
1437
  body = this.containers.map(c => renderContainerNode(ctx, c, 0));
1403
1438
  }
1404
- return (h(Host, { key: '2a092e3a7483deb1fb30753b0c0428aaf75c303a' }, h("div", { key: '2b716c912a272b925a95133de5b1ff2abedd9dbc', class: 'mrd-document-list' + (this.rootDropActive ? ' mrd-document-list--drop-active' : ''), onDragOver: this.onRootDragOver, onDragLeave: this.onRootDragLeave, onDrop: this.onRootDrop }, body)));
1439
+ return (h(Host, { key: '757babf3ccabbb113ab2a24d632b2b9a02d3c08b' }, h("div", { key: '606c212687482efdc5666333678e2ea406709e75', class: 'mrd-document-list' + (this.rootDropActive ? ' mrd-document-list--drop-active' : ''), onDragOver: this.onRootDragOver, onDragLeave: this.onRootDragLeave, onDrop: this.onRootDrop }, body)));
1405
1440
  }
1406
1441
  get el() { return getElement(this); }
1407
1442
  };
@@ -5316,6 +5351,10 @@ const MrdLayoutSection = class {
5316
5351
  /** Top-level archetypes on the object dashboard. When it contains commons.document,
5317
5352
  * the record is rendered as a single-document view instead of generic fields. */
5318
5353
  this.archetypes = [];
5354
+ /** When true, this dashboard is read-only (viewer role): the embedded mrd-table's
5355
+ * create ("+") action and the documents view's New folder / Upload are disabled
5356
+ * with a tooltip explaining why, so it's clear at a glance the user can't mutate data. */
5357
+ this.readOnly = false;
5319
5358
  this.searchQueryMap = {};
5320
5359
  this.searchResultsMap = {};
5321
5360
  this.imagePreviewUrl = null;
@@ -5521,7 +5560,7 @@ const MrdLayoutSection = class {
5521
5560
  * swaps between the folder tree and the flat table. Events are re-emitted to
5522
5561
  * the host with the view key, exactly as the raw list/table events were. */
5523
5562
  renderDocumentContainer(item, key, parentId, archetype, containerHref) {
5524
- return (h("mrd-document-container", { item: item, archetype: archetype, parentId: parentId, containerHref: containerHref, viewKey: key, locale: this.locale, onMrdLoadDistinct: (e) => {
5563
+ return (h("mrd-document-container", { item: item, archetype: archetype, parentId: parentId, containerHref: containerHref, viewKey: key, locale: this.locale, readOnly: this.readOnly, onMrdLoadDistinct: (e) => {
5525
5564
  e.stopPropagation();
5526
5565
  this.mrdLoadViewDistinct.emit(Object.assign({ name: key }, e.detail));
5527
5566
  }, onMrdLoadPage: (e) => {
@@ -5554,7 +5593,7 @@ const MrdLayoutSection = class {
5554
5593
  } }));
5555
5594
  }
5556
5595
  renderTable(item, key, parentId) {
5557
- return (h("mrd-table", { "data-view": key, item: item, parentId: parentId, locale: this.locale, onMrdLoadPage: (e) => this.handleViewLoadPage(e, key), onMrdLoadAggregations: (e) => {
5596
+ return (h("mrd-table", { "data-view": key, item: item, parentId: parentId, locale: this.locale, readOnly: this.readOnly, onMrdLoadPage: (e) => this.handleViewLoadPage(e, key), onMrdLoadAggregations: (e) => {
5558
5597
  var _a;
5559
5598
  e.stopPropagation();
5560
5599
  this.mrdLoadViewAggregations.emit(Object.assign({ name: key, dataClass: (_a = item.dataClass) !== null && _a !== void 0 ? _a : key }, e.detail));
@@ -5658,7 +5697,7 @@ const MrdLayoutSection = class {
5658
5697
  const docArchetype = resolveArchetype(this.archetypes, ARCHETYPE_DOCUMENT);
5659
5698
  const invoiceArchetype = !docArchetype ? resolveArchetype(this.archetypes, ARCHETYPE_INVOICE) : undefined;
5660
5699
  const emailArchetype = !docArchetype && !invoiceArchetype ? resolveArchetype(this.archetypes, ARCHETYPE_EMAIL) : undefined;
5661
- return (h(Host, { key: 'ccae8e82b4dd549ab24239fe685a6830a508061d' }, h("div", { key: '4072cc4ecdd2b087c54a5515e653f7f713b2150f', 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()));
5700
+ return (h(Host, { key: '07b1d61b170a5ae971ba54eaf775e1787dea1642' }, 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()));
5662
5701
  }
5663
5702
  get el() { return getElement(this); }
5664
5703
  static get watchers() { return {
@@ -6434,7 +6473,7 @@ const JsonModal = ({ html, locale, onClose }) => {
6434
6473
  return null;
6435
6474
  return (h("div", { class: "mrd-table__modal-backdrop", onClick: onClose, role: "dialog", "aria-modal": "true" }, h("div", { class: "mrd-table__modal", onClick: (e) => e.stopPropagation() }, h("button", { class: "mrd-table__modal-close", onClick: onClose, "aria-label": t('close', locale) }, "\u2715"), h("pre", { class: "mrd-table__modal-json", innerHTML: html }))));
6436
6475
  };
6437
- const Toolbar = ({ locale, filterCount, actions, views, activeViewIdx, viewPopoverOpen, createPickerOpen, createTypes, cb }) => {
6476
+ const Toolbar = ({ locale, filterCount, actions, views, activeViewIdx, viewPopoverOpen, createPickerOpen, createTypes, readOnly, cb }) => {
6438
6477
  var _a;
6439
6478
  const hasActions = actions.length > 0;
6440
6479
  const hasViewSwitcher = views.length > 1;
@@ -6445,14 +6484,18 @@ const Toolbar = ({ locale, filterCount, actions, views, activeViewIdx, viewPopov
6445
6484
  } }, v.label)))))), h("button", { class: "mrd-table__view-arrow", "aria-label": "Next view", onClick: () => cb.onViewSwitch((activeViewIdx + 1) % views.length) }, "\u25B6")))), hasActions && (h("div", { class: "mrd-table__toolbar-right" }, actions.map(a => {
6446
6485
  var _a, _b;
6447
6486
  const pickerTypes = a.action === 'create' ? createTypes : null;
6487
+ // readOnly only ever disables 'create' (see mrd-table.tsx tableActions) — export,
6488
+ // sorting and filtering don't mutate data and stay available.
6489
+ const disabled = a.disabled || (readOnly && a.action === 'create');
6490
+ const tooltip = disabled && readOnly ? t('readonly_access', locale) : a.label;
6448
6491
  if (pickerTypes === null || pickerTypes === void 0 ? void 0 : pickerTypes.length) {
6449
- return (h("div", { class: "mrd-table__create-picker-wrap", key: `action-${a.action}` }, h("button", { class: `mrd-table__action mrd-table__action--${(_a = a.variant) !== null && _a !== void 0 ? _a : 'secondary'}`, onClick: cb.onToggleCreatePicker }, a.icon
6492
+ return (h("div", { class: "mrd-table__create-picker-wrap", key: `action-${a.action}` }, h("button", { class: `mrd-table__action mrd-table__action--${(_a = a.variant) !== null && _a !== void 0 ? _a : 'secondary'}`, disabled: disabled, onClick: cb.onToggleCreatePicker }, a.icon
6450
6493
  ? h("svg", { class: "mrd-table__action-icon", "aria-hidden": "true" }, h("use", { href: a.icon }))
6451
- : a.label, h("span", { class: "mrd-table__action-tooltip" }, a.label)), createPickerOpen && (h("div", { class: "mrd-table__create-picker" }, pickerTypes.map(ct => (h("button", { key: ct.type, class: "mrd-table__create-picker-item", onClick: () => cb.onCreate(ct.type) }, ct.label)))))));
6494
+ : a.label, h("span", { class: "mrd-table__action-tooltip" }, tooltip)), createPickerOpen && (h("div", { class: "mrd-table__create-picker" }, pickerTypes.map(ct => (h("button", { key: ct.type, class: "mrd-table__create-picker-item", onClick: () => cb.onCreate(ct.type) }, ct.label)))))));
6452
6495
  }
6453
- return (h("button", { key: `action-${a.action}`, class: `mrd-table__action mrd-table__action--${(_b = a.variant) !== null && _b !== void 0 ? _b : 'secondary'}`, disabled: a.disabled, onClick: () => cb.onAction(a.action) }, a.icon
6496
+ return (h("button", { key: `action-${a.action}`, class: `mrd-table__action mrd-table__action--${(_b = a.variant) !== null && _b !== void 0 ? _b : 'secondary'}`, disabled: disabled, onClick: () => cb.onAction(a.action) }, a.icon
6454
6497
  ? h("svg", { class: "mrd-table__action-icon", "aria-hidden": "true" }, h("use", { href: a.icon }))
6455
- : a.label, h("span", { class: "mrd-table__action-tooltip" }, a.label)));
6498
+ : a.label, h("span", { class: "mrd-table__action-tooltip" }, tooltip)));
6456
6499
  })))));
6457
6500
  };
6458
6501
 
@@ -6673,6 +6716,10 @@ const MrdTable = class {
6673
6716
  /** Time (ms) to wait for setPage() before retrying a page request; after
6674
6717
  * MAX_RETRY_ATTEMPTS retries the page is marked failed (see failedPages). */
6675
6718
  this.requestTimeoutMs = REQUEST_TIMEOUT_MS;
6719
+ /** When true, the toolbar's create ("+") action is disabled (with a tooltip
6720
+ * explaining why) so a viewer-role user can see at a glance that this dashboard
6721
+ * is read-only. Sorting, filtering and export stay available — those don't mutate data. */
6722
+ this.readOnly = false;
6676
6723
  // ── Internal state ─────────────────────────────────────────────────────────
6677
6724
  /** Index into allViews[] for the currently displayed view. 0 = primary, 1+ = alternatives. */
6678
6725
  this.activeViewIdx = 0;
@@ -7242,7 +7289,7 @@ const MrdTable = class {
7242
7289
  const raw = (_b = (_a = this.item) === null || _a === void 0 ? void 0 : _a.actions) !== null && _b !== void 0 ? _b : [];
7243
7290
  return (raw !== null && raw !== void 0 ? raw : []).reduce((acc, a) => {
7244
7291
  if (a === 'NEW')
7245
- acc.push({ action: 'create', label: t('table_new_record', this.locale), icon: 'assets/sprites.svg#icon-plus', variant: 'primary' });
7292
+ acc.push({ action: 'create', label: t('table_new_record', this.locale), icon: 'assets/sprites.svg#icon-plus', variant: 'primary', disabled: this.readOnly });
7246
7293
  if (a === 'EXPORT')
7247
7294
  acc.push({ action: 'export', label: t('table_export_excel', this.locale), icon: 'assets/sprites.svg#icon-file-excel' });
7248
7295
  return acc;
@@ -7605,7 +7652,7 @@ const MrdTable = class {
7605
7652
  // ── Render: toolbar ────────────────────────────────────────────────────────
7606
7653
  renderToolbar() {
7607
7654
  var _a;
7608
- return (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, cb: {
7655
+ return (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: {
7609
7656
  onClearAllFilters: () => this.clearAllFilters(),
7610
7657
  onViewSwitch: idx => this.handleViewSwitch(idx),
7611
7658
  onToggleViewPopover: e => this.toggleViewPopover(e),
@@ -1,6 +1,6 @@
1
1
  import { h, r as registerInstance, c as createEvent, H as Host, g as getElement } from './index-CDiBvvJU.js';
2
2
  import { a as ClientLayoutItemType } from './client-layout-Bc42CfJB.js';
3
- import { t, C as CellRenderer, a as formatDate } from './cell-renderer-B8rJpnq8.js';
3
+ import { t, C as CellRenderer, a as formatDate } from './cell-renderer-CC8-MtvQ.js';
4
4
 
5
5
  /**
6
6
  * Whether a layout item can appear in the merge diff at all. m-n relations
@@ -1 +1 @@
1
- import{p as e,b as a}from"./p-CDiBvvJU.js";export{s as setNonce}from"./p-CDiBvvJU.js";import{g as l}from"./p-DQuL1Twl.js";(()=>{const a=import.meta.url,l={};return""!==a&&(l.resourcesUrl=new URL(".",a).href),e(l)})().then((async e=>(await l(),a([["p-e540de6a",[[2,"mrd-merge-view",{locale:[1],basicType:[1,"basic-type"],mostSignificantClass:[1,"most-significant-class"],fields:[16],currentHref:[1,"current-href"],currentRecord:[16],currentLabel:[1,"current-label"],step:[32],searchQuery:[32],searchResults:[32],isLoading:[32],candidate:[32],resolutions:[32],openHistoryKey:[32],setSearchResults:[64],setLoading:[64]}]]],["p-eb322d5c",[[2,"mrd-form",{layout:[16],locale:[1],values:[16],referenceHref:[1,"reference-href"],referenceClass:[1,"reference-class"],showCancel:[4,"show-cancel"],me:[16],formValues:[32],errors:[32],submitted:[32],setFieldValue:[64]},null,{values:[{valuesChanged:0}],me:[{meChanged:0}]}],[2,"mrd-layout-section",{items:[16],data:[16],views:[16],links:[16],locale:[1],archetypes:[16],searchQueryMap:[32],searchResultsMap:[32],imagePreviewUrl:[32],imagePreviews:[32],openHistoryField:[32],setSearchResults:[64],setViewPage:[64],setViewAggregations:[64],setViewDistinct:[64],setViewFileReference:[64],setViewCreatedObject:[64],setImagePreview:[64],openImagePreview:[64]},null,{data:[{dataChanged:0}]}],[2,"mrd-field",{item:[16],locale:[1],value:[16],historyEntries:[32],currentValue:[32]},null,{value:[{valueChanged:0}]}],[2,"mrd-document-container",{item:[16],archetype:[16],parentId:[1,"parent-id"],containerHref:[1,"container-href"],viewKey:[1,"view-key"],height:[2],locale:[1],mode:[32],canCreate:[32],targetLabel:[32]}],[2,"mrd-document-view",{archetype:[16],data:[16],locale:[1]},null,{data:[{dataChanged:0}]}],[2,"mrd-email-view",{archetype:[16],data:[16],locale:[1]},null,{data:[{dataChanged:0}]}],[262,"mrd-invoice-view",{archetype:[16],data:[16],locale:[1],statusListItems:[16]},null,{data:[{dataChanged:0}]}],[2,"mrd-boolean-field",{name:[1],label:[1],value:[4],required:[4],disabled:[4],locale:[1],checked:[32]}],[2,"mrd-currency-field",{name:[1],label:[1],value:[16],required:[4],disabled:[4],locale:[1],amountDisplay:[32],currency:[32],error:[32]},null,{value:[{valueChanged:0}],locale:[{localeChanged:0}]}],[2,"mrd-date-field",{name:[1],label:[1],value:[1],required:[4],disabled:[4],locale:[1],error:[32]}],[2,"mrd-datetime-field",{name:[1],label:[1],value:[1],required:[4],disabled:[4],locale:[1],error:[32],localValue:[32]},null,{value:[{valueChanged:0}]}],[2,"mrd-document-list",{item:[16],archetype:[16],parentId:[1,"parent-id"],containerHref:[1,"container-href"],locale:[1],containers:[32],rootLoading:[32],singleContainer:[32],selectedId:[32],dropTargetId:[32],uploadingNodeId:[32],rootDropActive:[32],setDistinct:[64],setDocuments:[64],createFolder:[64],uploadFile:[64],setFileReference:[64],setCreatedHref:[64]}],[2,"mrd-email-field",{name:[1],label:[1],value:[1],placeholder:[1],required:[4],disabled:[4],locale:[1],error:[32]}],[2,"mrd-file-field",{name:[1],label:[1],value:[16],required:[4],disabled:[4],locale:[1],accept:[1],maxSize:[2,"max-size"],multiple:[4],entries:[32],isDragging:[32],error:[32]},null,{value:[{valueChanged:0}]}],[2,"mrd-hyperlink-field",{name:[1],label:[1],value:[1],placeholder:[1],required:[4],disabled:[4],locale:[1],internalHref:[32],internalName:[32],error:[32]},null,{value:[{valueChanged:0}]}],[2,"mrd-image-field",{name:[1],label:[1],value:[16],required:[4],disabled:[4],locale:[1],accept:[1],maxSize:[2,"max-size"],multiple:[4],entries:[32],isDragging:[32],error:[32]},null,{value:[{valueChanged:0}]}],[2,"mrd-list-field",{name:[1],label:[1],value:[1],required:[4],disabled:[4],multiple:[4],locale:[1],listItems:[16],error:[32],selected:[32]}],[2,"mrd-longtext-field",{name:[1],label:[1],value:[1],placeholder:[1],required:[4],disabled:[4],locale:[1],error:[32]}],[2,"mrd-number-field",{name:[1],label:[1],value:[2],placeholder:[1],required:[4],disabled:[4],locale:[1],dataType:[1,"data-type"],decimalPrecision:[2,"decimal-precision"],displayValue:[32],error:[32]},null,{value:[{valueChanged:0}],locale:[{localeChanged:0}]}],[2,"mrd-relation-field",{name:[1],label:[1],required:[4],disabled:[4],locale:[1],relatedClass:[1,"related-class"],mostSignificantClass:[1,"most-significant-class"],displayType:[1,"display-type"],editBehavior:[1,"edit-behavior"],commonRelation:[1,"common-relation"],multiple:[4],dropdownValues:[16],value:[1],searchQuery:[32],searchResults:[32],allRecords:[32],isLoading:[32],selectedItems:[32],showResults:[32],error:[32],highlightedIndex:[32],setAllRecords:[64],setSearchResults:[64],setLoading:[64]},null,{allRecords:[{allRecordsChanged:0}],value:[{valueChanged:0}]}],[2,"mrd-secret-field",{name:[1],label:[1],value:[1],placeholder:[1],required:[4],disabled:[4],locale:[1],error:[32]}],[2,"mrd-table",{item:[16],parentId:[1,"parent-id"],rows:[16],locale:[1],totalElements:[2,"total-elements"],pageSize:[2,"page-size"],rowHeight:[2,"row-height"],tableHeight:[2,"table-height"],requestTimeoutMs:[2,"request-timeout-ms"],activeViewIdx:[32],loadedPages:[32],requestedPages:[32],failedPages:[32],renderStart:[32],renderEnd:[32],colWidths:[32],resizingCol:[32],sortField:[32],sortDir:[32],activeFilters:[32],openFilterCol:[32],pendingFilter:[32],popupPos:[32],createPickerOpen:[32],viewPopoverOpen:[32],scrollTop:[32],textblockModal:[32],jsonModal:[32],aggregations:[32],aggregationsTotal:[32],minKnownTotal:[32],init:[64],setPage:[64],setAggregations:[64]},null,{totalElements:[{totalElementsChanged:0}],item:[{itemChanged:0}]}],[2,"mrd-text-field",{name:[1],label:[1],value:[1],placeholder:[1],required:[4],disabled:[4],locale:[1],error:[32]}],[2,"mrd-textarea-field",{name:[1],label:[1],value:[1],placeholder:[1],required:[4],disabled:[4],locale:[1],error:[32],editorReady:[32]}],[2,"mrd-time-field",{name:[1],label:[1],value:[1],required:[4],disabled:[4],locale:[1],error:[32]}]]]],e))));
1
+ import{p as e,b as a}from"./p-CDiBvvJU.js";export{s as setNonce}from"./p-CDiBvvJU.js";import{g as l}from"./p-DQuL1Twl.js";(()=>{const a=import.meta.url,l={};return""!==a&&(l.resourcesUrl=new URL(".",a).href),e(l)})().then((async e=>(await l(),a([["p-a7e8f6a3",[[2,"mrd-merge-view",{locale:[1],basicType:[1,"basic-type"],mostSignificantClass:[1,"most-significant-class"],fields:[16],currentHref:[1,"current-href"],currentRecord:[16],currentLabel:[1,"current-label"],step:[32],searchQuery:[32],searchResults:[32],isLoading:[32],candidate:[32],resolutions:[32],openHistoryKey:[32],setSearchResults:[64],setLoading:[64]}]]],["p-07b148b2",[[2,"mrd-form",{layout:[16],locale:[1],values:[16],referenceHref:[1,"reference-href"],referenceClass:[1,"reference-class"],showCancel:[4,"show-cancel"],me:[16],formValues:[32],errors:[32],submitted:[32],setFieldValue:[64]},null,{values:[{valuesChanged:0}],me:[{meChanged:0}]}],[2,"mrd-layout-section",{items:[16],data:[16],views:[16],links:[16],locale:[1],archetypes:[16],readOnly:[4,"read-only"],searchQueryMap:[32],searchResultsMap:[32],imagePreviewUrl:[32],imagePreviews:[32],openHistoryField:[32],setSearchResults:[64],setViewPage:[64],setViewAggregations:[64],setViewDistinct:[64],setViewFileReference:[64],setViewCreatedObject:[64],setImagePreview:[64],openImagePreview:[64]},null,{data:[{dataChanged:0}]}],[2,"mrd-field",{item:[16],locale:[1],value:[16],historyEntries:[32],currentValue:[32]},null,{value:[{valueChanged:0}]}],[2,"mrd-document-container",{item:[16],archetype:[16],parentId:[1,"parent-id"],containerHref:[1,"container-href"],viewKey:[1,"view-key"],height:[2],locale:[1],readOnly:[4,"read-only"],mode:[32],canCreate:[32],targetLabel:[32]}],[2,"mrd-document-view",{archetype:[16],data:[16],locale:[1]},null,{data:[{dataChanged:0}]}],[2,"mrd-email-view",{archetype:[16],data:[16],locale:[1]},null,{data:[{dataChanged:0}]}],[262,"mrd-invoice-view",{archetype:[16],data:[16],locale:[1],statusListItems:[16]},null,{data:[{dataChanged:0}]}],[2,"mrd-boolean-field",{name:[1],label:[1],value:[4],required:[4],disabled:[4],locale:[1],checked:[32]}],[2,"mrd-currency-field",{name:[1],label:[1],value:[16],required:[4],disabled:[4],locale:[1],amountDisplay:[32],currency:[32],error:[32]},null,{value:[{valueChanged:0}],locale:[{localeChanged:0}]}],[2,"mrd-date-field",{name:[1],label:[1],value:[1],required:[4],disabled:[4],locale:[1],error:[32]}],[2,"mrd-datetime-field",{name:[1],label:[1],value:[1],required:[4],disabled:[4],locale:[1],error:[32],localValue:[32]},null,{value:[{valueChanged:0}]}],[2,"mrd-document-list",{item:[16],archetype:[16],parentId:[1,"parent-id"],containerHref:[1,"container-href"],locale:[1],readOnly:[4,"read-only"],containers:[32],rootLoading:[32],singleContainer:[32],selectedId:[32],dropTargetId:[32],uploadingNodeId:[32],rootDropActive:[32],setDistinct:[64],setDocuments:[64],createFolder:[64],uploadFile:[64],setFileReference:[64],setCreatedHref:[64]}],[2,"mrd-email-field",{name:[1],label:[1],value:[1],placeholder:[1],required:[4],disabled:[4],locale:[1],error:[32]}],[2,"mrd-file-field",{name:[1],label:[1],value:[16],required:[4],disabled:[4],locale:[1],accept:[1],maxSize:[2,"max-size"],multiple:[4],entries:[32],isDragging:[32],error:[32]},null,{value:[{valueChanged:0}]}],[2,"mrd-hyperlink-field",{name:[1],label:[1],value:[1],placeholder:[1],required:[4],disabled:[4],locale:[1],internalHref:[32],internalName:[32],error:[32]},null,{value:[{valueChanged:0}]}],[2,"mrd-image-field",{name:[1],label:[1],value:[16],required:[4],disabled:[4],locale:[1],accept:[1],maxSize:[2,"max-size"],multiple:[4],entries:[32],isDragging:[32],error:[32]},null,{value:[{valueChanged:0}]}],[2,"mrd-list-field",{name:[1],label:[1],value:[1],required:[4],disabled:[4],multiple:[4],locale:[1],listItems:[16],error:[32],selected:[32]}],[2,"mrd-longtext-field",{name:[1],label:[1],value:[1],placeholder:[1],required:[4],disabled:[4],locale:[1],error:[32]}],[2,"mrd-number-field",{name:[1],label:[1],value:[2],placeholder:[1],required:[4],disabled:[4],locale:[1],dataType:[1,"data-type"],decimalPrecision:[2,"decimal-precision"],displayValue:[32],error:[32]},null,{value:[{valueChanged:0}],locale:[{localeChanged:0}]}],[2,"mrd-relation-field",{name:[1],label:[1],required:[4],disabled:[4],locale:[1],relatedClass:[1,"related-class"],mostSignificantClass:[1,"most-significant-class"],displayType:[1,"display-type"],editBehavior:[1,"edit-behavior"],commonRelation:[1,"common-relation"],multiple:[4],dropdownValues:[16],value:[1],searchQuery:[32],searchResults:[32],allRecords:[32],isLoading:[32],selectedItems:[32],showResults:[32],error:[32],highlightedIndex:[32],setAllRecords:[64],setSearchResults:[64],setLoading:[64]},null,{allRecords:[{allRecordsChanged:0}],value:[{valueChanged:0}]}],[2,"mrd-secret-field",{name:[1],label:[1],value:[1],placeholder:[1],required:[4],disabled:[4],locale:[1],error:[32]}],[2,"mrd-table",{item:[16],parentId:[1,"parent-id"],rows:[16],locale:[1],totalElements:[2,"total-elements"],pageSize:[2,"page-size"],rowHeight:[2,"row-height"],tableHeight:[2,"table-height"],requestTimeoutMs:[2,"request-timeout-ms"],readOnly:[4,"read-only"],activeViewIdx:[32],loadedPages:[32],requestedPages:[32],failedPages:[32],renderStart:[32],renderEnd:[32],colWidths:[32],resizingCol:[32],sortField:[32],sortDir:[32],activeFilters:[32],openFilterCol:[32],pendingFilter:[32],popupPos:[32],createPickerOpen:[32],viewPopoverOpen:[32],scrollTop:[32],textblockModal:[32],jsonModal:[32],aggregations:[32],aggregationsTotal:[32],minKnownTotal:[32],init:[64],setPage:[64],setAggregations:[64]},null,{totalElements:[{totalElementsChanged:0}],item:[{itemChanged:0}]}],[2,"mrd-text-field",{name:[1],label:[1],value:[1],placeholder:[1],required:[4],disabled:[4],locale:[1],error:[32]}],[2,"mrd-textarea-field",{name:[1],label:[1],value:[1],placeholder:[1],required:[4],disabled:[4],locale:[1],error:[32],editorReady:[32]}],[2,"mrd-time-field",{name:[1],label:[1],value:[1],required:[4],disabled:[4],locale:[1],error:[32]}]]]],e))));