@mmlogic/components 0.5.12 → 0.5.14

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 (53) hide show
  1. package/dist/cjs/{cell-renderer-pwUGEDql.js → cell-renderer-mjS630f1.js} +16 -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 +212 -45
  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.css +36 -0
  10. package/dist/collection/components/table/mrd-table/mrd-table.js +162 -26
  11. package/dist/collection/components/table/mrd-table/table-parts.js +14 -6
  12. package/dist/collection/components/table/mrd-table/table-query.js +6 -0
  13. package/dist/collection/dev/app.js +24 -0
  14. package/dist/collection/utils/i18n.js +16 -0
  15. package/dist/components/i18n.js +1 -1
  16. package/dist/components/mrd-document-container2.js +1 -1
  17. package/dist/components/mrd-document-list2.js +1 -1
  18. package/dist/components/mrd-layout-section.js +1 -1
  19. package/dist/components/mrd-table2.js +1 -1
  20. package/dist/esm/{cell-renderer-B8rJpnq8.js → cell-renderer-BDY8UXkH.js} +16 -0
  21. package/dist/esm/loader.js +1 -1
  22. package/dist/esm/mosterdcomponents.js +1 -1
  23. package/dist/esm/mrd-boolean-field_25.entry.js +212 -45
  24. package/dist/esm/mrd-merge-view.entry.js +1 -1
  25. package/dist/mosterdcomponents/cell-renderer-B8u5BCK-.js.map +1 -0
  26. package/dist/mosterdcomponents/client-layout-Bc42CfJB.js.map +1 -0
  27. package/dist/mosterdcomponents/document-attachments-BufPmMRv.js.map +1 -0
  28. package/dist/mosterdcomponents/field-helpers-CNQcI3Hf.js.map +1 -0
  29. package/dist/mosterdcomponents/file-upload-common-C9wp47CB.js.map +1 -0
  30. package/dist/mosterdcomponents/format-gcecItcD.js.map +1 -0
  31. package/dist/mosterdcomponents/i18n-ydNM87-Q.js.map +1 -0
  32. package/dist/mosterdcomponents/index-1ayBojyN.js.map +1 -0
  33. package/dist/mosterdcomponents/index-DhffneUF.js.map +1 -0
  34. package/dist/mosterdcomponents/index.esm.js.map +1 -0
  35. package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
  36. package/dist/mosterdcomponents/mosterdcomponents.esm.js.map +1 -0
  37. package/dist/mosterdcomponents/p-Dkm4WxMy.js +1 -0
  38. package/dist/mosterdcomponents/p-c834951a.entry.js +3 -0
  39. package/dist/mosterdcomponents/{p-e540de6a.entry.js → p-e8b0880f.entry.js} +1 -1
  40. package/dist/mosterdcomponents/purify.es-_duHfPgC.js.map +1 -0
  41. package/dist/mosterdcomponents/query-params-BZbQoeYF.js.map +1 -0
  42. package/dist/mosterdcomponents/quill-C9pgw_k-.js.map +1 -0
  43. package/dist/mosterdcomponents/validation-CjjTt66G.js.map +1 -0
  44. package/dist/types/components/documents/mrd-document-container/mrd-document-container.d.ts +4 -0
  45. package/dist/types/components/documents/mrd-document-list/mrd-document-list.d.ts +6 -1
  46. package/dist/types/components/layout/mrd-layout-section/mrd-layout-section.d.ts +4 -0
  47. package/dist/types/components/table/mrd-table/mrd-table.d.ts +52 -1
  48. package/dist/types/components/table/mrd-table/table-parts.d.ts +18 -0
  49. package/dist/types/components/table/mrd-table/table-query.d.ts +6 -0
  50. package/dist/types/components.d.ts +45 -1
  51. package/package.json +1 -1
  52. package/dist/mosterdcomponents/p-eb322d5c.entry.js +0 -3
  53. package/dist/mosterdcomponents/p-rTM1tU_M.js +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-CjjTt66G.js","sources":["src/utils/validation.ts"],"sourcesContent":["import { ClientLayoutItemFieldDataType } from '../types';\n\nexport function validateRequired(value: unknown): boolean {\n if (value === null || value === undefined) return false;\n if (typeof value === 'string') return value.trim().length > 0;\n if (Array.isArray(value)) return value.length > 0;\n if (typeof value === 'object') {\n // HyperlinkValue check\n const hv = value as { href?: unknown };\n if ('href' in hv) return typeof hv.href === 'string' && hv.href.trim().length > 0;\n // CurrencyValue check\n const cv = value as { amount?: unknown };\n if ('amount' in cv) return cv.amount !== null && cv.amount !== undefined && cv.amount !== '';\n }\n return true;\n}\n\nexport function validateEmail(value: string): boolean {\n if (!value) return true;\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value);\n}\n\nexport function validateUrl(value: string): boolean {\n if (!value) return true;\n try {\n const url = new URL(value);\n return url.protocol === 'http:' || url.protocol === 'https:';\n } catch {\n return false;\n }\n}\n\nexport function validateNumber(value: unknown, dataType: ClientLayoutItemFieldDataType): boolean {\n if (value === null || value === undefined || value === '') return true;\n const num = Number(value);\n if (isNaN(num)) return false;\n if (dataType === ClientLayoutItemFieldDataType.INTEGER) {\n return Number.isInteger(num);\n }\n if (dataType === ClientLayoutItemFieldDataType.PERCENTAGE) {\n return num >= 0 && num <= 100;\n }\n return true;\n}\n"],"names":[],"mappings":";;;AAEM,SAAU,gBAAgB,CAAC,KAAc,EAAA;AAC7C,IAAA,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;AAAE,QAAA,OAAO,KAAK;IACvD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;AAC7D,IAAA,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;AAAE,QAAA,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC;AACjD,IAAA,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;;QAE7B,MAAM,EAAE,GAAG,KAA2B;QACtC,IAAI,MAAM,IAAI,EAAE;AAAE,YAAA,OAAO,OAAO,EAAE,CAAC,IAAI,KAAK,QAAQ,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;;QAEjF,MAAM,EAAE,GAAG,KAA6B;QACxC,IAAI,QAAQ,IAAI,EAAE;AAAE,YAAA,OAAO,EAAE,CAAC,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC,MAAM,KAAK,SAAS,IAAI,EAAE,CAAC,MAAM,KAAK,EAAE;;AAE9F,IAAA,OAAO,IAAI;AACb;AAEM,SAAU,aAAa,CAAC,KAAa,EAAA;AACzC,IAAA,IAAI,CAAC,KAAK;AAAE,QAAA,OAAO,IAAI;AACvB,IAAA,OAAO,4BAA4B,CAAC,IAAI,CAAC,KAAK,CAAC;AACjD;AAEM,SAAU,WAAW,CAAC,KAAa,EAAA;AACvC,IAAA,IAAI,CAAC,KAAK;AAAE,QAAA,OAAO,IAAI;AACvB,IAAA,IAAI;AACF,QAAA,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC;QAC1B,OAAO,GAAG,CAAC,QAAQ,KAAK,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ;;IAC5D,OAAA,EAAA,EAAM;AACN,QAAA,OAAO,KAAK;;AAEhB;AAEM,SAAU,cAAc,CAAC,KAAc,EAAE,QAAuC,EAAA;IACpF,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,EAAE;AAAE,QAAA,OAAO,IAAI;AACtE,IAAA,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC;IACzB,IAAI,KAAK,CAAC,GAAG,CAAC;AAAE,QAAA,OAAO,KAAK;AAC5B,IAAA,IAAI,QAAQ,KAAK,6BAA6B,CAAC,OAAO,EAAE;AACtD,QAAA,OAAO,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC;;AAE9B,IAAA,IAAI,QAAQ,KAAK,6BAA6B,CAAC,UAAU,EAAE;AACzD,QAAA,OAAO,GAAG,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG;;AAE/B,IAAA,OAAO,IAAI;AACb;;;;"}
@@ -29,6 +29,10 @@ export declare class MrdDocumentContainer {
29
29
  * on top, Finder-style. The table manages its own height. */
30
30
  height: number;
31
31
  locale: string;
32
+ /** When true, this dashboard is read-only: New folder and Upload are disabled
33
+ * (with a tooltip explaining why) and the embedded table/list get it passed
34
+ * through so their own create/upload/drag-drop paths are disabled too. */
35
+ readOnly: boolean;
32
36
  /** Re-emitted from the embedded list/table. `nodeId` present for a folder load. */
33
37
  mrdLoadPage: EventEmitter<{
34
38
  page: number;
@@ -33,6 +33,11 @@ export declare class MrdDocumentList {
33
33
  * accepts file drops and folder creation. */
34
34
  containerHref: string;
35
35
  locale: string;
36
+ /** When true, folder creation, file upload (button and drag-drop) and moving a
37
+ * document between folders are all disabled — a viewer-role user can browse
38
+ * but not mutate anything. Drives mrdCanCreate(false) so the host toolbar's
39
+ * New folder / Upload buttons stay disabled too. */
40
+ readOnly: boolean;
36
41
  /** Request distinct values for a field/relation. Host fetches `{path}?{qs}` and calls `setDistinct(nodeId, values)`. */
37
42
  mrdLoadDistinct: EventEmitter<{
38
43
  nodeId: string;
@@ -181,7 +186,7 @@ export declare class MrdDocumentList {
181
186
  private resolveTarget;
182
187
  private get canCreateFolder();
183
188
  /** Start creating a folder under the current target. Called by the host toolbar
184
- * (mrd-document-container). No-op when there is no valid target. */
189
+ * (mrd-document-container). No-op when there is no valid target, or read-only. */
185
190
  createFolder(): Promise<void>;
186
191
  private startCreateFolder;
187
192
  private onPendingInput;
@@ -18,6 +18,10 @@ export declare class MrdLayoutSection {
18
18
  /** Top-level archetypes on the object dashboard. When it contains commons.document,
19
19
  * the record is rendered as a single-document view instead of generic fields. */
20
20
  archetypes: ClientArchetype[];
21
+ /** When true, this dashboard is read-only (viewer role): the embedded mrd-table's
22
+ * create ("+") action and the documents view's New folder / Upload are disabled
23
+ * with a tooltip explaining why, so it's clear at a glance the user can't mutate data. */
24
+ readOnly: boolean;
21
25
  private searchQueryMap;
22
26
  private searchResultsMap;
23
27
  private imagePreviewUrl;
@@ -15,6 +15,17 @@ export declare class MrdTable {
15
15
  private keydownHandler;
16
16
  private createPickerClickHandler;
17
17
  private viewPopoverClickHandler;
18
+ /** Debounce timer for the free-text search box — separate from debounceTimer
19
+ * (pending-page requests), since typing and scrolling debounce independently. */
20
+ private searchDebounceTimer;
21
+ /** The rendered search <input>, captured so it can be focused the instant it mounts. */
22
+ private searchInputEl;
23
+ /** Set by toggleSearch() when the box just expanded; consumed and cleared in componentDidRender(). */
24
+ private searchNeedsFocus;
25
+ /** Column filters stashed by stashFiltersForSearch() while the search box is open — the
26
+ * backend can't combine `q` with column filters. Restored by restoreFiltersAfterSearch()
27
+ * on close, unless the user applied a fresh filter of their own in the meantime. */
28
+ private stashedFilters;
18
29
  /** Watches the host for gaining a box (e.g. its tab pane being shown) — see componentDidLoad. */
19
30
  private resizeObserver;
20
31
  /** Guards against scheduling more than one column-width measurement per freeze. */
@@ -48,6 +59,10 @@ export declare class MrdTable {
48
59
  /** Time (ms) to wait for setPage() before retrying a page request; after
49
60
  * MAX_RETRY_ATTEMPTS retries the page is marked failed (see failedPages). */
50
61
  requestTimeoutMs: number;
62
+ /** When true, the toolbar's create ("+") action is disabled (with a tooltip
63
+ * explaining why) so a viewer-role user can see at a glance that this dashboard
64
+ * is read-only. Sorting, filtering and export stay available — those don't mutate data. */
65
+ readOnly: boolean;
51
66
  /** Clamp renderEnd when totalElements shrinks (e.g. after a filter is applied).
52
67
  * 0 means "unknown" (hosts that rely on minKnownTotal never set it, and some reset it
53
68
  * while a filter is being applied) — clamping to it would collapse the window to a
@@ -70,6 +85,10 @@ export declare class MrdTable {
70
85
  sortDir: 'asc' | 'desc';
71
86
  /** Active filters keyed by field name. */
72
87
  activeFilters: Map<string, ColumnFilter>;
88
+ /** True while the toolbar's magnifying glass is expanded into the search input. */
89
+ private searchOpen;
90
+ /** Current free-text search query — sent as `q` on every mrdLoadPage/aggregations request. */
91
+ private searchQuery;
73
92
  /** Field name of the currently open filter popup (null = closed). */
74
93
  openFilterCol: string | null;
75
94
  /** Filter state being edited in the open popup. */
@@ -254,7 +273,13 @@ export declare class MrdTable {
254
273
  * VIEW: /{dataClass}
255
274
  * RELATED_VIEW: /{fromClass}/{parentId}/{dataClass} */
256
275
  private buildDataPath;
257
- /** Build query params for a page request from current sort, view filters, filterClass and active column filters. */
276
+ /** Build query params for a page request from current sort, view filters, filterClass and active column filters.
277
+ *
278
+ * `q` and column filters are mutually exclusive on the backend — combining them breaks
279
+ * the search. stashFiltersForSearch() already empties activeFilters for the duration of
280
+ * a search, but this guard is the actual guarantee: even if a filter is applied through
281
+ * a column header while the search box is still open (before the query is cleared),
282
+ * activeFilters is dropped from the request rather than sent alongside `q`. */
258
283
  private buildQueryParams;
259
284
  /** True when the table is in paginated / virtual-scroll mode rather than driven by the
260
285
  * rows prop. Mirrors the branch taken in render().
@@ -302,9 +327,35 @@ export declare class MrdTable {
302
327
  private closeJsonModal;
303
328
  private setPending;
304
329
  private togglePendingValue;
330
+ /** Common reload after activeFilters or searchQuery changed: drop stale aggregations
331
+ * (the next setPage(0) re-requests them, guarded against `q` in setPage() itself) and
332
+ * re-fetch page 0. Shared by the filter popup, clear-all, and free-text search. */
333
+ private reloadAfterQueryChange;
305
334
  private applyFilter;
306
335
  private clearFilter;
307
336
  private clearAllFilters;
337
+ /** Search is a VIEW-only affordance — a RELATED_VIEW table is already scoped to
338
+ * its parent record, so a free-text box there would invite confusion about what
339
+ * it searches across. */
340
+ private get searchEnabled();
341
+ private toggleSearch;
342
+ /** Collapses the box back to the icon. Clearing a non-empty query and restoring any
343
+ * stashed filters can each independently require a reload — reloadAfterQueryChange()
344
+ * is called at most once here regardless of how many of the two actually changed. */
345
+ private closeSearch;
346
+ private handleSearchInput;
347
+ /** Reloads from page 0 with the current searchQuery, same reset as applyFilter(). */
348
+ private applySearch;
349
+ /** Column filters and the free-text `q` param are mutually exclusive on the backend —
350
+ * sending both breaks the search. Opening the search box stashes any active filters
351
+ * and clears them (the header filter icons and the clear-all button disappear along
352
+ * with activeFilters, so there is nothing extra to hide) and reloads unfiltered. */
353
+ private stashFiltersForSearch;
354
+ /** Restores filters stashed by stashFiltersForSearch(), unless the user applied a fresh
355
+ * filter of their own while the search box was open — that explicit choice wins over
356
+ * reinstating the old one. Returns whether activeFilters actually changed, so the
357
+ * caller can decide whether a reload is needed. */
358
+ private restoreFiltersAfterSearch;
308
359
  private handleViewSwitch;
309
360
  private toggleViewPopover;
310
361
  private closeViewPopover;
@@ -6,6 +6,9 @@ import { AggregationResult, ClientCreateType } from '../../../types/client-layou
6
6
  * component; these components receive plain values and callbacks.
7
7
  */
8
8
  export declare const FilterIcon: FunctionalComponent;
9
+ export declare const SearchIcon: FunctionalComponent<{
10
+ class?: string;
11
+ }>;
9
12
  export declare const TableCell: FunctionalComponent<{
10
13
  col: TableColumn;
11
14
  row: Record<string, any>;
@@ -43,6 +46,14 @@ export interface ToolbarCallbacks {
43
46
  /** Emit the create action; basicType set when chosen from the create-type picker. */
44
47
  onCreate: (basicType?: string) => void;
45
48
  onAction: (action: string) => void;
49
+ /** Expand the collapsed magnifying-glass icon into the search input, or collapse it back. */
50
+ onToggleSearch: () => void;
51
+ /** Free-text search input changed; caller debounces before reloading. */
52
+ onSearchInput: (value: string) => void;
53
+ /** Clear the query and collapse the search box back to the icon. */
54
+ onCloseSearch: () => void;
55
+ /** Captures the rendered <input> so the caller can focus it the instant it mounts. */
56
+ onSearchInputRef: (el?: HTMLInputElement) => void;
46
57
  }
47
58
  export declare const Toolbar: FunctionalComponent<{
48
59
  locale: string;
@@ -55,5 +66,12 @@ export declare const Toolbar: FunctionalComponent<{
55
66
  viewPopoverOpen: boolean;
56
67
  createPickerOpen: boolean;
57
68
  createTypes?: ClientCreateType[] | null;
69
+ /** True when a viewer-role user has read-only access: mutating actions are
70
+ * disabled and their tooltip explains why instead of just repeating the label. */
71
+ readOnly?: boolean;
72
+ /** True only for a top-level VIEW item — RELATED_VIEW tables never show free-text search. */
73
+ searchEnabled?: boolean;
74
+ searchOpen?: boolean;
75
+ searchQuery?: string;
58
76
  cb: ToolbarCallbacks;
59
77
  }>;
@@ -10,6 +10,10 @@ export declare const DATE_TYPES: Set<string>;
10
10
  export declare const NO_FILTER_TYPES: Set<string>;
11
11
  /** Column types that cannot be sorted or filtered (not stored in PostgreSQL). */
12
12
  export declare const NON_INTERACTIVE_TYPES: Set<string>;
13
+ /** Wait this long (ms) after the user stops typing in the free-text search box
14
+ * before firing the search request — mirrors REQUEST_DEBOUNCE_MS's purpose
15
+ * (skip intermediate keystrokes) but is tuned for typing, not scrolling. */
16
+ export declare const SEARCH_DEBOUNCE_MS = 400;
13
17
  export declare function parseDefaultSort(defaultSort: string): {
14
18
  field: string;
15
19
  dir: 'asc' | 'desc';
@@ -23,6 +27,8 @@ export declare function buildTableQueryParams(opts: {
23
27
  filterClass?: string | null;
24
28
  viewFilters?: ViewFilter[] | null;
25
29
  activeFilters: Iterable<ColumnFilter>;
30
+ /** Free-text search query from the toolbar's search box (VIEW only). */
31
+ query?: string;
26
32
  }): string;
27
33
  /** Groups aggregate columns by function; null when the view has no aggregates. */
28
34
  export declare function buildAggregationParams(columns: TableColumn[]): {
@@ -161,6 +161,11 @@ export namespace Components {
161
161
  * @default ''
162
162
  */
163
163
  "parentId": string;
164
+ /**
165
+ * When true, this dashboard is read-only: New folder and Upload are disabled (with a tooltip explaining why) and the embedded table/list get it passed through so their own create/upload/drag-drop paths are disabled too.
166
+ * @default false
167
+ */
168
+ "readOnly": boolean;
164
169
  /**
165
170
  * Lookup key used for the embedded `data-doclist` / `data-view` attributes.
166
171
  * @default ''
@@ -193,7 +198,7 @@ export namespace Components {
193
198
  */
194
199
  "containerHref": string;
195
200
  /**
196
- * Start creating a folder under the current target. Called by the host toolbar (mrd-document-container). No-op when there is no valid target.
201
+ * Start creating a folder under the current target. Called by the host toolbar (mrd-document-container). No-op when there is no valid target, or read-only.
197
202
  */
198
203
  "createFolder": () => Promise<void>;
199
204
  /**
@@ -210,6 +215,11 @@ export namespace Components {
210
215
  * @default ''
211
216
  */
212
217
  "parentId": string;
218
+ /**
219
+ * When true, folder creation, file upload (button and drag-drop) and moving a document between folders are all disabled — a viewer-role user can browse but not mutate anything. Drives mrdCanCreate(false) so the host toolbar's New folder / Upload buttons stay disabled too.
220
+ * @default false
221
+ */
222
+ "readOnly": boolean;
213
223
  /**
214
224
  * Host callback with the created document's self href, so the optimistic row becomes navigable without waiting for a reload.
215
225
  */
@@ -529,6 +539,11 @@ export namespace Components {
529
539
  * Open the lightbox directly with a URL (e.g. after mrdDownload on a FILE field).
530
540
  */
531
541
  "openImagePreview": (url: string) => Promise<void>;
542
+ /**
543
+ * When true, this dashboard is read-only (viewer role): the embedded mrd-table's create ("+") action and the documents view's New folder / Upload are disabled with a tooltip explaining why, so it's clear at a glance the user can't mutate data.
544
+ * @default false
545
+ */
546
+ "readOnly": boolean;
532
547
  /**
533
548
  * Provide a resolved URL for an IMAGE field. Shows as thumbnail; clicking opens the lightbox.
534
549
  */
@@ -824,6 +839,11 @@ export namespace Components {
824
839
  * @default ''
825
840
  */
826
841
  "parentId": string;
842
+ /**
843
+ * When true, the toolbar's create ("+") action is disabled (with a tooltip explaining why) so a viewer-role user can see at a glance that this dashboard is read-only. Sorting, filtering and export stay available — those don't mutate data.
844
+ * @default false
845
+ */
846
+ "readOnly": boolean;
827
847
  /**
828
848
  * Time (ms) to wait for setPage() before retrying a page request; after MAX_RETRY_ATTEMPTS retries the page is marked failed (see failedPages).
829
849
  * @default 15000
@@ -1848,6 +1868,11 @@ declare namespace LocalJSX {
1848
1868
  * @default ''
1849
1869
  */
1850
1870
  "parentId"?: string;
1871
+ /**
1872
+ * When true, this dashboard is read-only: New folder and Upload are disabled (with a tooltip explaining why) and the embedded table/list get it passed through so their own create/upload/drag-drop paths are disabled too.
1873
+ * @default false
1874
+ */
1875
+ "readOnly"?: boolean;
1851
1876
  /**
1852
1877
  * Lookup key used for the embedded `data-doclist` / `data-view` attributes.
1853
1878
  * @default ''
@@ -1925,6 +1950,11 @@ declare namespace LocalJSX {
1925
1950
  * @default ''
1926
1951
  */
1927
1952
  "parentId"?: string;
1953
+ /**
1954
+ * When true, folder creation, file upload (button and drag-drop) and moving a document between folders are all disabled — a viewer-role user can browse but not mutate anything. Drives mrdCanCreate(false) so the host toolbar's New folder / Upload buttons stay disabled too.
1955
+ * @default false
1956
+ */
1957
+ "readOnly"?: boolean;
1928
1958
  }
1929
1959
  /**
1930
1960
  * Archetype-driven single-document view. Given a `commons.document` binding and a
@@ -2320,6 +2350,11 @@ declare namespace LocalJSX {
2320
2350
  * An external file was dropped on a document view; host uploads and calls setViewFileReference(name, uri).
2321
2351
  */
2322
2352
  "onMrdViewUpload"?: (event: MrdLayoutSectionCustomEvent<{ name: string; file: File }>) => void;
2353
+ /**
2354
+ * When true, this dashboard is read-only (viewer role): the embedded mrd-table's create ("+") action and the documents view's New folder / Upload are disabled with a tooltip explaining why, so it's clear at a glance the user can't mutate data.
2355
+ * @default false
2356
+ */
2357
+ "readOnly"?: boolean;
2323
2358
  /**
2324
2359
  * Legacy: view metadata map (ClientDashboardMetadata.views). Not needed in new flat format.
2325
2360
  * @default {}
@@ -2613,6 +2648,11 @@ declare namespace LocalJSX {
2613
2648
  * @default ''
2614
2649
  */
2615
2650
  "parentId"?: string;
2651
+ /**
2652
+ * When true, the toolbar's create ("+") action is disabled (with a tooltip explaining why) so a viewer-role user can see at a glance that this dashboard is read-only. Sorting, filtering and export stay available — those don't mutate data.
2653
+ * @default false
2654
+ */
2655
+ "readOnly"?: boolean;
2616
2656
  /**
2617
2657
  * Time (ms) to wait for setPage() before retrying a page request; after MAX_RETRY_ATTEMPTS retries the page is marked failed (see failedPages).
2618
2658
  * @default 15000
@@ -2769,11 +2809,13 @@ declare namespace LocalJSX {
2769
2809
  "viewKey": string;
2770
2810
  "height": number;
2771
2811
  "locale": string;
2812
+ "readOnly": boolean;
2772
2813
  }
2773
2814
  interface MrdDocumentListAttributes {
2774
2815
  "parentId": string;
2775
2816
  "containerHref": string;
2776
2817
  "locale": string;
2818
+ "readOnly": boolean;
2777
2819
  }
2778
2820
  interface MrdDocumentViewAttributes {
2779
2821
  "locale": string;
@@ -2833,6 +2875,7 @@ declare namespace LocalJSX {
2833
2875
  }
2834
2876
  interface MrdLayoutSectionAttributes {
2835
2877
  "locale": string;
2878
+ "readOnly": boolean;
2836
2879
  }
2837
2880
  interface MrdListFieldAttributes {
2838
2881
  "name": string;
@@ -2901,6 +2944,7 @@ declare namespace LocalJSX {
2901
2944
  "rowHeight": number;
2902
2945
  "tableHeight": number;
2903
2946
  "requestTimeoutMs": number;
2947
+ "readOnly": boolean;
2904
2948
  }
2905
2949
  interface MrdTextFieldAttributes {
2906
2950
  "name": string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmlogic/components",
3
- "version": "0.5.12",
3
+ "version": "0.5.14",
4
4
  "description": "Stencil.js web component library for dynamic forms and virtual-scroll data tables",
5
5
  "license": "MIT",
6
6
  "author": "Mosterd",