@mmlogic/components 0.5.15 → 0.5.17

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 (40) hide show
  1. package/dist/cjs/loader.cjs.js +1 -1
  2. package/dist/cjs/mosterdcomponents.cjs.js +1 -1
  3. package/dist/cjs/mrd-boolean-field_28.cjs.entry.js +361 -56
  4. package/dist/collection/collection-manifest.json +2 -2
  5. package/dist/collection/components/documents/mrd-document-container/mrd-document-container.js +31 -4
  6. package/dist/collection/components/form/mrd-field/mrd-field.css +69 -0
  7. package/dist/collection/components/form/mrd-field/mrd-field.js +95 -25
  8. package/dist/collection/components/layout/mrd-layout-section/field-value.js +19 -2
  9. package/dist/collection/components/layout/mrd-layout-section/layout-helpers.js +10 -0
  10. package/dist/collection/components/layout/mrd-layout-section/mrd-layout-section.css +4 -3
  11. package/dist/collection/components/layout/mrd-layout-section/mrd-layout-section.js +174 -17
  12. package/dist/collection/components/memo/mrd-memo-container/mrd-memo-container.js +105 -6
  13. package/dist/collection/components/memo/mrd-memo-list/mrd-memo-list.css +14 -0
  14. package/dist/collection/components/memo/mrd-memo-list/mrd-memo-list.js +50 -2
  15. package/dist/collection/components/table/mrd-table/mrd-table.js +105 -2
  16. package/dist/collection/dev/api.js +17 -0
  17. package/dist/collection/dev/app.js +49 -15
  18. package/dist/collection/dev/example-data.js +15 -1
  19. package/dist/components/mrd-document-container2.js +1 -1
  20. package/dist/components/mrd-field2.js +1 -1
  21. package/dist/components/mrd-layout-section.js +1 -1
  22. package/dist/components/mrd-memo-container2.js +1 -1
  23. package/dist/components/mrd-memo-list2.js +1 -1
  24. package/dist/components/mrd-table2.js +1 -1
  25. package/dist/esm/loader.js +1 -1
  26. package/dist/esm/mosterdcomponents.js +1 -1
  27. package/dist/esm/mrd-boolean-field_28.entry.js +361 -56
  28. package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
  29. package/dist/mosterdcomponents/p-f72668e9.entry.js +3 -0
  30. package/dist/types/components/documents/mrd-document-container/mrd-document-container.d.ts +7 -0
  31. package/dist/types/components/form/mrd-field/mrd-field.d.ts +16 -0
  32. package/dist/types/components/layout/mrd-layout-section/field-value.d.ts +4 -0
  33. package/dist/types/components/layout/mrd-layout-section/layout-helpers.d.ts +3 -0
  34. package/dist/types/components/layout/mrd-layout-section/mrd-layout-section.d.ts +52 -0
  35. package/dist/types/components/memo/mrd-memo-container/mrd-memo-container.d.ts +26 -1
  36. package/dist/types/components/memo/mrd-memo-list/mrd-memo-list.d.ts +12 -0
  37. package/dist/types/components/table/mrd-table/mrd-table.d.ts +45 -0
  38. package/dist/types/components.d.ts +92 -0
  39. package/package.json +1 -1
  40. package/dist/mosterdcomponents/p-d64ba1f2.entry.js +0 -3
@@ -33,6 +33,13 @@ export declare class MrdDocumentContainer {
33
33
  * (with a tooltip explaining why) and the embedded table/list get it passed
34
34
  * through so their own create/upload/drag-drop paths are disabled too. */
35
35
  readOnly: boolean;
36
+ /** Whether the current user may create a document here — set by mrd-layout-section from
37
+ * its generic capability check (TASK-0299/FINDING-0155), the same answer the embedded
38
+ * table gets in list mode. Named `mayCreate` (not `canCreate`) to avoid colliding with
39
+ * the existing `canCreate` state below, which tracks something unrelated: whether the
40
+ * folder tree currently has a valid drop target selected. Defaults to false (hidden)
41
+ * until confirmed, same as mrd-table. */
42
+ mayCreate: boolean;
36
43
  /** Re-emitted from the embedded list/table. `nodeId` present for a folder load. */
37
44
  mrdLoadPage: EventEmitter<{
38
45
  page: number;
@@ -35,9 +35,19 @@ export declare class MrdField {
35
35
  until: string;
36
36
  }>;
37
37
  currentValue: unknown;
38
+ multiValues: unknown[];
39
+ multiError: string;
38
40
  componentWillLoad(): void;
39
41
  valueChanged(): void;
40
42
  private initHistoryState;
43
+ /** LIST/FILE/IMAGE already own their multiple-value UI end to end; every
44
+ * other scalar dataType routes through the generic repeater below instead
45
+ * of each leaf field re-implementing add/remove itself (FINDING-0149). */
46
+ private isMultiScalar;
47
+ private initMultiState;
48
+ private emptyRowValue;
49
+ private emitMultiChange;
50
+ private handleMultiRowBlur;
41
51
  private handleChange;
42
52
  private handleBlur;
43
53
  private handleSearch;
@@ -46,7 +56,13 @@ export declare class MrdField {
46
56
  private getDisplayValue;
47
57
  private historyValueInputType;
48
58
  private emitHistoryChange;
59
+ private renderRemoveIcon;
49
60
  private renderHistoryEditor;
50
61
  private renderLeafField;
62
+ /** Repeatable-row UI for a scalar dataType with multiple: true — mirrors the
63
+ * add/remove pattern already established by renderHistoryEditor(), reusing
64
+ * the single-row renderLeafField() per entry instead of duplicating repeat
65
+ * UI into every leaf field component (FINDING-0149). */
66
+ private renderMultiScalarField;
51
67
  render(): any;
52
68
  }
@@ -19,4 +19,8 @@ export interface FieldViewContext {
19
19
  };
20
20
  }
21
21
  export declare function renderFieldValue(ctx: FieldViewContext, item: ClientLayoutItem, rawValue: unknown): any;
22
+ /** Whether a FIELD item would render anything at all (value, or a showEmpty
23
+ * placeholder). A `header` field always renders. Used by mrd-layout-section
24
+ * to decide whether a preceding HEADER item's block is entirely empty. */
25
+ export declare function isFieldVisible(ctx: FieldViewContext, item: ClientLayoutItem): boolean;
22
26
  export declare function renderField(ctx: FieldViewContext, item: ClientLayoutItem): any;
@@ -4,6 +4,9 @@ export declare function viewKeyFor(item: ClientLayoutItem): string;
4
4
  /** Whether a FIELD/RELATION item stays visible on an OBJECT_DASHBOARD when it
5
5
  * has no value. Reads the flat API flag, falling back to the nested wrappers. */
6
6
  export declare function showsEmpty(item: ClientLayoutItem): boolean;
7
+ /** Whether a RELATION item has a resolvable link value (`_links[item.name]`
8
+ * carries either a multi-value `values[]` or a single `name`). */
9
+ export declare function hasRelationValue(item: ClientLayoutItem, data: Record<string, unknown>): boolean;
7
10
  /** Depth-first flatten of the SECTION/GROUP tree. */
8
11
  export declare function flattenItems(items: ClientLayoutItem[]): ClientLayoutItem[];
9
12
  /** Build the canonical parent href `/{base}/{tenant}/{fromClass}/{parentId}` from
@@ -32,7 +32,16 @@ export declare class MrdLayoutSection {
32
32
  private imagePreviewUrl;
33
33
  private imagePreviews;
34
34
  private openHistoryField;
35
+ /** Answers to mrdViewCheckCapabilities, keyed by view key — see emitCapabilitiesChecks().
36
+ * Passed straight down as a `canCreate`/`mayCreate` prop to whichever body (mrd-table,
37
+ * mrd-memo-container, mrd-document-container) is mounted for that key; a missing entry
38
+ * means "not answered yet" and is treated as false (hidden), same default as mrd-table's
39
+ * own standalone behaviour (TASK-0299). */
40
+ private canCreateMap;
35
41
  private historyClickOutside;
42
+ /** Signature last asked per view key (see emitCapabilitiesChecks()) — avoids re-emitting
43
+ * mrdViewCheckCapabilities on every data/items update when the binding hasn't changed. */
44
+ private capabilitiesAsked;
36
45
  /** `attachments`, when present, prefetches the clicked document row's file slot
37
46
  * (see TASK-0169 / FINDING-0111) so the host can render a preview immediately,
38
47
  * without waiting for the navigated-to page's own mrdAttachments. Only set for
@@ -101,6 +110,17 @@ export declare class MrdLayoutSection {
101
110
  path: string;
102
111
  qs: string;
103
112
  }>;
113
+ /** Emitted once per VIEW/RELATED_VIEW binding — computed here directly, not relayed from a
114
+ * child (see emitCapabilitiesChecks()), so it covers mrd-table, mrd-memo-container and
115
+ * mrd-document-container uniformly. `name` is the view key (viewKeyFor(item)) — pass it
116
+ * back to setViewCanCreate() to answer it. */
117
+ mrdViewCheckCapabilities: EventEmitter<{
118
+ name: string;
119
+ type: string;
120
+ refType?: string;
121
+ refId?: string;
122
+ filterClass?: string;
123
+ }>;
104
124
  /** Generic "update an existing object" request from an embedded document view
105
125
  * (a document dragged into another folder). Host PATCHes `href` with `values`. */
106
126
  mrdUpdateObject: EventEmitter<{
@@ -129,8 +149,29 @@ export declare class MrdLayoutSection {
129
149
  componentDidLoad(): void;
130
150
  disconnectedCallback(): void;
131
151
  dataChanged(newVal: Record<string, unknown>): void;
152
+ /** A host can swap `items` (e.g. a different dashboard layout) without `data` changing —
153
+ * dataChanged() alone would miss that binding change. */
154
+ itemsChanged(): void;
132
155
  private initEmbeddedTables;
133
156
  private emitLoadImages;
157
+ /** Parent record id extracted from `data._links.self.href` — the same value every
158
+ * VIEW/RELATED_VIEW item on this record shares, used for RELATED_VIEW path construction
159
+ * (renderRelatedView) and capability checks (emitCapabilitiesChecks). */
160
+ private computeParentId;
161
+ /** Asks, once per VIEW/RELATED_VIEW binding, whether the current user may create a record
162
+ * there — the single generic place for this check (TASK-0299/FINDING-0155), so mrd-table,
163
+ * mrd-memo-container and mrd-document-container all get the answer the same way: as a plain
164
+ * `canCreate`/`mayCreate` prop from this component, computed here and handed down in
165
+ * renderTable()/renderMemoContainer()/renderDocumentContainer() — none of the three leaf
166
+ * components need to ask on their own when rendered through mrd-layout-section (mrd-table's
167
+ * own self-ask only kicks in for standalone use, i.e. its `canCreate` prop left undefined).
168
+ *
169
+ * The route/path variables mirror what each renderer already uses for its own rows —
170
+ * `type` = `dataClass`, `refType`/`refId` = `fromClass`/parentId for a RELATED_VIEW, and
171
+ * `filterClass` when the view is scoped to one subtype (the same value sent as `?type=` on
172
+ * the row fetch). A signature (not just the key) is tracked per binding so a genuine route
173
+ * change re-asks and hides again, without re-asking on every unrelated data/items update. */
174
+ private emitCapabilitiesChecks;
134
175
  /** Inject search results. Pass dataClass to target a specific SEARCH item; omit when there is only one. */
135
176
  setSearchResults(results: RelationSearchResult[], dataClass?: string): Promise<void>;
136
177
  /**
@@ -142,6 +183,12 @@ export declare class MrdLayoutSection {
142
183
  setViewPage(name: string, page: number, rows: any[], totalElements?: number, hasNext?: boolean, nodeId?: string): Promise<void>;
143
184
  /** Inject aggregation totals into an embedded mrd-table for a VIEW or RELATED_VIEW item. */
144
185
  setViewAggregations(name: string, data: any): Promise<void>;
186
+ /** Host answer to mrdViewCheckCapabilities — whether the current user may create a record
187
+ * for the given view's bound route. `name` is the view key from the event detail. Stored in
188
+ * canCreateMap and passed down as a plain prop to whichever body is mounted for that key
189
+ * (mrd-table, mrd-memo-container or mrd-document-container) — no DOM lookup needed, unlike
190
+ * setViewPage/setViewAggregations, since the prop flows through the next render. */
191
+ setViewCanCreate(name: string, value: boolean): Promise<void>;
145
192
  /** Inject distinct values into an embedded mrd-document-list for a document view. */
146
193
  setViewDistinct(name: string, nodeId: string, values: DistinctValue[]): Promise<void>;
147
194
  /** Inject the uploaded file reference for a dropped file, so the document view
@@ -172,6 +219,11 @@ export declare class MrdLayoutSection {
172
219
  * the card list and the flat table, mirroring renderDocumentContainer(). */
173
220
  private renderMemoContainer;
174
221
  private renderTable;
222
+ /** Whether every FIELD/RELATION item following a HEADER (up to the next
223
+ * HEADER/SECTION/GROUP or the end of `siblings`) would itself render
224
+ * nothing — i.e. the HEADER would introduce an empty block. Other item
225
+ * types (VIEW, NAVIGATE, TEXT, ...) always count as visible. */
226
+ private isHeaderBlockEmpty;
175
227
  private renderItem;
176
228
  private renderImageModal;
177
229
  /** Related VIEW/RELATED_VIEW/SEARCH items to keep rendering below an archetype's
@@ -28,6 +28,20 @@ export declare class MrdMemoContainer {
28
28
  /** Canonical parent href — set when this is a RELATED_VIEW embedded under a
29
29
  * parent record, which already gives a new memo something to attach to. */
30
30
  containerHref: string;
31
+ /** False when this RELATED_VIEW's parent is related via a relation other than
32
+ * the archetype's container slot (e.g. a person's "memos I authored" list,
33
+ * related via `author`) — mrd-layout-section resolves this from the item's
34
+ * `inverseRelation`. In that case the parent is not a valid container for a
35
+ * new memo, and — unlike a top-level VIEW with no context at all — falling
36
+ * back to `me` would be wrong too (creating a memo "on myself" from someone
37
+ * else's authored-memos list makes no sense), so "New memo" is hidden outright. */
38
+ containerRelated: boolean;
39
+ /** True unless this is a container-scoped RELATED_VIEW (a company's own memo
40
+ * tab, say) where every card's container is obviously the page you're
41
+ * already on — forwarded to mrd-memo-list to show/hide its per-card
42
+ * container link. A top-level VIEW or an author-scoped RELATED_VIEW both
43
+ * still need it, since the container isn't implied by the page context. */
44
+ showContainerLink: boolean;
31
45
  /** Lookup key used for the embedded `data-view` attribute. */
32
46
  viewKey: string;
33
47
  locale: string;
@@ -38,6 +52,10 @@ export declare class MrdMemoContainer {
38
52
  * tooltip, cards/rows are not clickable, and the embedded table's own
39
53
  * create action is disabled too. */
40
54
  readOnly: boolean;
55
+ /** Whether the current user may create a memo here — set by mrd-layout-section from its
56
+ * generic capability check (TASK-0299/FINDING-0155), the same answer the embedded table
57
+ * gets in table mode. Defaults to false (hidden) until confirmed, same as mrd-table. */
58
+ canCreate: boolean;
41
59
  /** The active account's linked person record (userProfile.links.person), if any.
42
60
  * Used both to gate "New memo" (see effectiveContainerHref) and, on submit, to
43
61
  * fill the author slot. */
@@ -53,6 +71,12 @@ export declare class MrdMemoContainer {
53
71
  qs: string;
54
72
  aggQs: string;
55
73
  }>;
74
+ /** A card's container link was clicked — real navigation, unrelated to the
75
+ * quick-edit dialog (mrdEdit is internal, handled by this component itself). */
76
+ mrdNavigate: EventEmitter<{
77
+ href?: string;
78
+ label: string;
79
+ }>;
56
80
  /** Only the embedded table's own toolbar (export, etc.) still routes through this. */
57
81
  mrdAction: EventEmitter<{
58
82
  action: string;
@@ -124,7 +148,8 @@ export declare class MrdMemoContainer {
124
148
  private get hasTitleSlot();
125
149
  private get hasImportantSlot();
126
150
  /** A parent record already gives a new memo somewhere to attach to (RELATED_VIEW);
127
- * otherwise fall back to the account's own linked person (top-level VIEW). */
151
+ * otherwise fall back to the account's own linked person (top-level VIEW) — but
152
+ * only when containerRelated allows it (see its doc comment). */
128
153
  private get effectiveContainerHref();
129
154
  /** The author slot is always filled from `me` (there is no author picker in
130
155
  * the dialog), so without it there is nothing valid to create — regardless
@@ -32,6 +32,11 @@ export declare class MrdMemoList {
32
32
  /** listItems of the FIELD bound to the `labels` slot, resolved by mrd-layout-section
33
33
  * from its own items array, same reason mrd-memo-view needs it. */
34
34
  labelsListItems: ClientListValue[] | null;
35
+ /** False when the list is already scoped to its own container (a company's own
36
+ * memo tab) — showing "belongs to: <this same company>" on every card there
37
+ * would be redundant. True everywhere else (top-level VIEW, or a RELATED_VIEW
38
+ * scoped by a different relation, e.g. a person's authored-memos list). */
39
+ showContainerLink: boolean;
35
40
  /** Fired when a page needs fetching; same shape as mrd-table's mrdLoadPage minus `qs`'s
36
41
  * column-filter support (cards have no filter UI) — host calls setPage() with the result. */
37
42
  mrdLoadPage: EventEmitter<{
@@ -45,6 +50,12 @@ export declare class MrdMemoList {
45
50
  mrdEdit: EventEmitter<{
46
51
  row: Record<string, unknown>;
47
52
  }>;
53
+ /** The container link on a card was clicked — this is real navigation (to the
54
+ * container record), unrelated to mrdEdit. */
55
+ mrdNavigate: EventEmitter<{
56
+ href?: string;
57
+ label: string;
58
+ }>;
48
59
  private rows;
49
60
  private loading;
50
61
  private exhausted;
@@ -72,6 +83,7 @@ export declare class MrdMemoList {
72
83
  private slotLink;
73
84
  private plainTextLength;
74
85
  private toggleExpanded;
86
+ private renderContainer;
75
87
  private renderLabels;
76
88
  private renderBody;
77
89
  private renderCard;
@@ -63,6 +63,13 @@ export declare class MrdTable {
63
63
  * explaining why) so a viewer-role user can see at a glance that this dashboard
64
64
  * is read-only. Sorting, filtering and export stay available — those don't mutate data. */
65
65
  readOnly: boolean;
66
+ /** Whether the current user may create a record for the table's bound route. Leave
67
+ * `undefined` for standalone use — the table then asks on its own via mrdCheckCapabilities
68
+ * and hides the create button until setCanCreate() answers. Set it explicitly when a host
69
+ * already knows the answer (e.g. mrd-layout-section, which asks once per binding and hands
70
+ * the answer to whichever body it mounts) — the table then trusts it directly and never
71
+ * asks on its own (TASK-0299). */
72
+ canCreate?: boolean;
66
73
  /** Clamp renderEnd when totalElements shrinks (e.g. after a filter is applied).
67
74
  * 0 means "unknown" (hosts that rely on minKnownTotal never set it, and some reset it
68
75
  * while a filter is being applied) — clamping to it would collapse the window to a
@@ -70,6 +77,11 @@ export declare class MrdTable {
70
77
  totalElementsChanged(newVal: number): void;
71
78
  /** Reset to primary view when the item prop is replaced from outside. */
72
79
  itemChanged(newVal: ClientLayoutItem | null): void;
80
+ /** A parent-record navigation can reuse the same `item` reference while only `parentId`
81
+ * changes (e.g. clicking a different dossier for the same RELATED_VIEW layout) — itemChanged()
82
+ * would not fire for that. Re-ask so a stale canCreate answer from the previous parent never
83
+ * leaks into the new one. */
84
+ parentIdChanged(): void;
73
85
  /** Index into allViews[] for the currently displayed view. 0 = primary, 1+ = alternatives. */
74
86
  private activeViewIdx;
75
87
  loadedPages: Map<number, Record<string, any>[]>;
@@ -116,6 +128,10 @@ export declare class MrdTable {
116
128
  private aggregationsPending;
117
129
  /** Lower bound on total derived from setPage() hasNext info; grows as pages load. */
118
130
  private minKnownTotal;
131
+ /** Self-asked answer for standalone use (the `canCreate` prop is undefined) — defaults to
132
+ * hidden (TASK-0299) until the host answers mrdCheckCapabilities via setCanCreate(). Ignored
133
+ * when the host controls `canCreate` directly; see effectiveCanCreate(). */
134
+ private selfCanCreate;
119
135
  /** Fired when a page needs to be fetched. Host fetches and calls setPage().
120
136
  * `sort` is the raw query-param value, e.g. "name" or "name,desc". */
121
137
  mrdLoadPage: EventEmitter<{
@@ -160,6 +176,21 @@ export declare class MrdTable {
160
176
  qs: string;
161
177
  aggQs: string;
162
178
  }>;
179
+ /** Standalone use only (never fires while the `canCreate` prop is set — see there). Fired
180
+ * once per table binding (initial load, and whenever the bound item, parent record or active
181
+ * view changes) to ask the host whether the current user may create a record here. Carries
182
+ * the same route the table already uses for its own rows, unconstructed — VIEW:
183
+ * GET /data/{tenant}/{type}/capabilities; RELATED_VIEW: GET /data/{tenant}/{refType}/{refId}/{type}/capabilities.
184
+ * `filterClass`, when the view declares one, is the same subtype the row fetch sends as
185
+ * `?type=` — e.g. a "contents" RELATED_VIEW filtered to `document` asks specifically whether
186
+ * a document may be created here, not any content type.
187
+ * The add button stays hidden until the host calls setCanCreate() (FINDING-0155 / TASK-0299). */
188
+ mrdCheckCapabilities: EventEmitter<{
189
+ type: string;
190
+ refType?: string;
191
+ refId?: string;
192
+ filterClass?: string;
193
+ }>;
163
194
  componentWillLoad(): void;
164
195
  componentDidLoad(): void;
165
196
  private applyDefaultSort;
@@ -183,6 +214,12 @@ export declare class MrdTable {
183
214
  setPage(pageNumber: number, rows: Record<string, any>[], hasNext?: boolean): Promise<void>;
184
215
  /** Inject aggregation totals returned by the /aggregations endpoint. */
185
216
  setAggregations(data: AggregationResult): Promise<void>;
217
+ /** Host answer to mrdCheckCapabilities — whether the current user may create a record for
218
+ * the table's currently bound route (standalone use only; ignored while the `canCreate`
219
+ * prop is set, since the host controls it directly in that mode). Call it any time after
220
+ * the event fires; a stale answer for an old binding is discarded automatically
221
+ * (selfCanCreate is reset to false before every new mrdCheckCapabilities emission). */
222
+ setCanCreate(value: boolean): Promise<void>;
186
223
  disconnectedCallback(): void;
187
224
  componentDidRender(): void;
188
225
  /** Freeze the column widths once the first data page has rendered.
@@ -273,6 +310,12 @@ export declare class MrdTable {
273
310
  * VIEW: /{dataClass}
274
311
  * RELATED_VIEW: /{fromClass}/{parentId}/{dataClass} */
275
312
  private buildDataPath;
313
+ /** Asks the host whether creating is allowed for the table's current binding (item, parent
314
+ * and active view) — only in standalone use (`canCreate` prop undefined). A host that
315
+ * controls `canCreate` directly already knows the answer, so the table never asks on its
316
+ * own in that mode. Resets selfCanCreate to false first so the add button stays hidden for
317
+ * the new binding until the host answers — it never inherits the previous binding's answer. */
318
+ private emitCapabilitiesCheck;
276
319
  /** Build query params for a page request from current sort, view filters, filterClass and active column filters.
277
320
  *
278
321
  * `q` and column filters are mutually exclusive on the backend — combining them breaks
@@ -291,6 +334,8 @@ export declare class MrdTable {
291
334
  * mode must not flip back to the rows prop (and its "no results") while page 0 is in flight. */
292
335
  private get isPaginated();
293
336
  private get columns();
337
+ /** `canCreate` when the host controls it directly, else the table's own self-asked answer. */
338
+ private get effectiveCanCreate();
294
339
  private get tableActions();
295
340
  private toggleCreatePicker;
296
341
  private closeCreatePicker;
@@ -156,6 +156,11 @@ export namespace Components {
156
156
  * @default navigator.language
157
157
  */
158
158
  "locale": string;
159
+ /**
160
+ * Whether the current user may create a document here — set by mrd-layout-section from its generic capability check (TASK-0299/FINDING-0155), the same answer the embedded table gets in list mode. Named `mayCreate` (not `canCreate`) to avoid colliding with the existing `canCreate` state below, which tracks something unrelated: whether the folder tree currently has a valid drop target selected. Defaults to false (hidden) until confirmed, same as mrd-table.
161
+ * @default false
162
+ */
163
+ "mayCreate": boolean;
159
164
  /**
160
165
  * Parent record id — required for RELATED_VIEW path building.
161
166
  * @default ''
@@ -566,6 +571,10 @@ export namespace Components {
566
571
  * Inject aggregation totals into an embedded mrd-table for a VIEW or RELATED_VIEW item.
567
572
  */
568
573
  "setViewAggregations": (name: string, data: any) => Promise<void>;
574
+ /**
575
+ * Host answer to mrdViewCheckCapabilities — whether the current user may create a record for the given view's bound route. `name` is the view key from the event detail. Stored in canCreateMap and passed down as a plain prop to whichever body is mounted for that key (mrd-table, mrd-memo-container or mrd-document-container) — no DOM lookup needed, unlike setViewPage/setViewAggregations, since the prop flows through the next render.
576
+ */
577
+ "setViewCanCreate": (name: string, value: boolean) => Promise<void>;
569
578
  /**
570
579
  * Inject the created document's href after a file-drop create, so the optimistic row becomes navigable (see mrdCreateObject). For a memo quick-create there is no optimistic row to resolve — simply reload the container's current body so the new memo shows up.
571
580
  */
@@ -674,11 +683,21 @@ export namespace Components {
674
683
  * Resolved `commons.memo` archetype binding.
675
684
  */
676
685
  "archetype": ClientArchetype;
686
+ /**
687
+ * Whether the current user may create a memo here — set by mrd-layout-section from its generic capability check (TASK-0299/FINDING-0155), the same answer the embedded table gets in table mode. Defaults to false (hidden) until confirmed, same as mrd-table.
688
+ * @default false
689
+ */
690
+ "canCreate": boolean;
677
691
  /**
678
692
  * Canonical parent href — set when this is a RELATED_VIEW embedded under a parent record, which already gives a new memo something to attach to.
679
693
  * @default ''
680
694
  */
681
695
  "containerHref": string;
696
+ /**
697
+ * False when this RELATED_VIEW's parent is related via a relation other than the archetype's container slot (e.g. a person's "memos I authored" list, related via `author`) — mrd-layout-section resolves this from the item's `inverseRelation`. In that case the parent is not a valid container for a new memo, and — unlike a top-level VIEW with no context at all — falling back to `me` would be wrong too (creating a memo "on myself" from someone else's authored-memos list makes no sense), so "New memo" is hidden outright.
698
+ * @default true
699
+ */
700
+ "containerRelated": boolean;
682
701
  /**
683
702
  * The VIEW or RELATED_VIEW layout item (dataClass, fromClass, view config).
684
703
  * @default null
@@ -712,6 +731,11 @@ export namespace Components {
712
731
  * Re-request page 0 of whichever body is currently mounted — called by mrd-layout-section after a successful mrdCreateObject, and by this component itself after an edit to a table row (which has no per-row optimistic-patch method the way mrd-memo-list does).
713
732
  */
714
733
  "refresh": () => Promise<void>;
734
+ /**
735
+ * True unless this is a container-scoped RELATED_VIEW (a company's own memo tab, say) where every card's container is obviously the page you're already on — forwarded to mrd-memo-list to show/hide its per-card container link. A top-level VIEW or an author-scoped RELATED_VIEW both still need it, since the container isn't implied by the page context.
736
+ * @default true
737
+ */
738
+ "showContainerLink": boolean;
715
739
  /**
716
740
  * Lookup key used for the embedded `data-view` attribute.
717
741
  * @default ''
@@ -782,6 +806,11 @@ export namespace Components {
782
806
  * Inject the rows for a page (0-based); page 0 replaces, later pages append.
783
807
  */
784
808
  "setPage": (pageNumber: number, rows: Record<string, unknown>[], hasNext?: boolean) => Promise<void>;
809
+ /**
810
+ * False when the list is already scoped to its own container (a company's own memo tab) — showing "belongs to: <this same company>" on every card there would be redundant. True everywhere else (top-level VIEW, or a RELATED_VIEW scoped by a different relation, e.g. a person's authored-memos list).
811
+ * @default true
812
+ */
813
+ "showContainerLink": boolean;
785
814
  }
786
815
  /**
787
816
  * Archetype-driven single-memo view. Given a `commons.memo` binding and a data
@@ -982,6 +1011,10 @@ export namespace Components {
982
1011
  "value": string;
983
1012
  }
984
1013
  interface MrdTable {
1014
+ /**
1015
+ * Whether the current user may create a record for the table's bound route. Leave `undefined` for standalone use — the table then asks on its own via mrdCheckCapabilities and hides the create button until setCanCreate() answers. Set it explicitly when a host already knows the answer (e.g. mrd-layout-section, which asks once per binding and hands the answer to whichever body it mounts) — the table then trusts it directly and never asks on its own (TASK-0299).
1016
+ */
1017
+ "canCreate"?: boolean;
985
1018
  /**
986
1019
  * Initialise (or reset) the virtual scroll. Call after setting all props and registering the mrdLoadPage listener, but before calling setPage(0, rows).
987
1020
  */
@@ -1029,6 +1062,10 @@ export namespace Components {
1029
1062
  * Inject aggregation totals returned by the /aggregations endpoint.
1030
1063
  */
1031
1064
  "setAggregations": (data: AggregationResult) => Promise<void>;
1065
+ /**
1066
+ * Host answer to mrdCheckCapabilities — whether the current user may create a record for the table's currently bound route (standalone use only; ignored while the `canCreate` prop is set, since the host controls it directly in that mode). Call it any time after the event fires; a stale answer for an old binding is discarded automatically (selfCanCreate is reset to false before every new mrdCheckCapabilities emission).
1067
+ */
1068
+ "setCanCreate": (value: boolean) => Promise<void>;
1032
1069
  /**
1033
1070
  * Inject the rows for a given page (0-based). Creates a new Map reference so Stencil detects the state change. When the page contains fewer rows than pageSize it is the last page. renderEnd is clamped immediately so no loading-placeholder rows appear beyond the actual data — without requiring the host to update totalElements. Pass hasNext (from _links.next in the API response) for accurate last-page detection even when rows.length === pageSize (exact multiple of page size).
1034
1071
  */
@@ -1623,6 +1660,7 @@ declare global {
1623
1660
  "mrdViewAction": { name: string; action: string; dataClass: string; path?: string; qs?: string; parentPath?: string | null; basicType?: string };
1624
1661
  "mrdLoadViewAggregations": { name: string; dataClass: string; path: string; qs: string; aggQs: string };
1625
1662
  "mrdLoadViewDistinct": { name: string; nodeId: string; distinct: string; path: string; qs: string };
1663
+ "mrdViewCheckCapabilities": { name: string; type: string; refType?: string; refId?: string; filterClass?: string };
1626
1664
  "mrdUpdateObject": { href: string; values: Record<string, unknown> };
1627
1665
  "mrdDeleteObject": { href: string };
1628
1666
  "mrdViewUpload": { name: string; file: File };
@@ -1681,6 +1719,7 @@ declare global {
1681
1719
  interface HTMLMrdMemoContainerElementEventMap {
1682
1720
  "mrdLoadPage": { page: number; sort: string; path: string; qs: string };
1683
1721
  "mrdLoadAggregations": { path: string; qs: string; aggQs: string };
1722
+ "mrdNavigate": { href?: string; label: string };
1684
1723
  "mrdAction": { action: string; path?: string; qs?: string; parentPath?: string | null; basicType?: string };
1685
1724
  "mrdCreateObject": { path: string; values: Record<string, unknown> };
1686
1725
  "mrdUpdateObject": { href: string; values: Record<string, unknown> };
@@ -1719,6 +1758,7 @@ declare global {
1719
1758
  interface HTMLMrdMemoListElementEventMap {
1720
1759
  "mrdLoadPage": { page: number; sort: string; path: string; qs: string };
1721
1760
  "mrdEdit": { row: Record<string, unknown> };
1761
+ "mrdNavigate": { href?: string; label: string };
1722
1762
  }
1723
1763
  /**
1724
1764
  * Card-view body for a `commons.memo` collection — the alternative to the flat
@@ -1862,6 +1902,7 @@ declare global {
1862
1902
  "mrdAction": { action: string; path?: string; qs?: string; dataClass?: string; parentPath?: string | null; basicType?: string };
1863
1903
  "mrdDownload": { href: string; fileName: string };
1864
1904
  "mrdLoadAggregations": { path: string; qs: string; aggQs: string };
1905
+ "mrdCheckCapabilities": { type: string; refType?: string; refId?: string; filterClass?: string };
1865
1906
  }
1866
1907
  interface HTMLMrdTableElement extends Components.MrdTable, HTMLStencilElement {
1867
1908
  addEventListener<K extends keyof HTMLMrdTableElementEventMap>(type: K, listener: (this: HTMLMrdTableElement, ev: MrdTableCustomEvent<HTMLMrdTableElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
@@ -2112,6 +2153,11 @@ declare namespace LocalJSX {
2112
2153
  * @default navigator.language
2113
2154
  */
2114
2155
  "locale"?: string;
2156
+ /**
2157
+ * Whether the current user may create a document here — set by mrd-layout-section from its generic capability check (TASK-0299/FINDING-0155), the same answer the embedded table gets in list mode. Named `mayCreate` (not `canCreate`) to avoid colliding with the existing `canCreate` state below, which tracks something unrelated: whether the folder tree currently has a valid drop target selected. Defaults to false (hidden) until confirmed, same as mrd-table.
2158
+ * @default false
2159
+ */
2160
+ "mayCreate"?: boolean;
2115
2161
  /**
2116
2162
  * A table toolbar action was triggered.
2117
2163
  */
@@ -2642,6 +2688,10 @@ declare namespace LocalJSX {
2642
2688
  * Re-emitted from an embedded mrd-table's mrdAction; host builds the target URL from dataClass.
2643
2689
  */
2644
2690
  "onMrdViewAction"?: (event: MrdLayoutSectionCustomEvent<{ name: string; action: string; dataClass: string; path?: string; qs?: string; parentPath?: string | null; basicType?: string }>) => void;
2691
+ /**
2692
+ * Emitted once per VIEW/RELATED_VIEW binding — computed here directly, not relayed from a child (see emitCapabilitiesChecks()), so it covers mrd-table, mrd-memo-container and mrd-document-container uniformly. `name` is the view key (viewKeyFor(item)) — pass it back to setViewCanCreate() to answer it.
2693
+ */
2694
+ "onMrdViewCheckCapabilities"?: (event: MrdLayoutSectionCustomEvent<{ name: string; type: string; refType?: string; refId?: string; filterClass?: string }>) => void;
2645
2695
  /**
2646
2696
  * An external file was dropped on a document view; host uploads and calls setViewFileReference(name, uri).
2647
2697
  */
@@ -2747,11 +2797,21 @@ declare namespace LocalJSX {
2747
2797
  * Resolved `commons.memo` archetype binding.
2748
2798
  */
2749
2799
  "archetype": ClientArchetype;
2800
+ /**
2801
+ * Whether the current user may create a memo here — set by mrd-layout-section from its generic capability check (TASK-0299/FINDING-0155), the same answer the embedded table gets in table mode. Defaults to false (hidden) until confirmed, same as mrd-table.
2802
+ * @default false
2803
+ */
2804
+ "canCreate"?: boolean;
2750
2805
  /**
2751
2806
  * Canonical parent href — set when this is a RELATED_VIEW embedded under a parent record, which already gives a new memo something to attach to.
2752
2807
  * @default ''
2753
2808
  */
2754
2809
  "containerHref"?: string;
2810
+ /**
2811
+ * False when this RELATED_VIEW's parent is related via a relation other than the archetype's container slot (e.g. a person's "memos I authored" list, related via `author`) — mrd-layout-section resolves this from the item's `inverseRelation`. In that case the parent is not a valid container for a new memo, and — unlike a top-level VIEW with no context at all — falling back to `me` would be wrong too (creating a memo "on myself" from someone else's authored-memos list makes no sense), so "New memo" is hidden outright.
2812
+ * @default true
2813
+ */
2814
+ "containerRelated"?: boolean;
2755
2815
  /**
2756
2816
  * The VIEW or RELATED_VIEW layout item (dataClass, fromClass, view config).
2757
2817
  * @default null
@@ -2785,6 +2845,10 @@ declare namespace LocalJSX {
2785
2845
  "onMrdDeleteObject"?: (event: MrdMemoContainerCustomEvent<{ href: string }>) => void;
2786
2846
  "onMrdLoadAggregations"?: (event: MrdMemoContainerCustomEvent<{ path: string; qs: string; aggQs: string }>) => void;
2787
2847
  "onMrdLoadPage"?: (event: MrdMemoContainerCustomEvent<{ page: number; sort: string; path: string; qs: string }>) => void;
2848
+ /**
2849
+ * A card's container link was clicked — real navigation, unrelated to the quick-edit dialog (mrdEdit is internal, handled by this component itself).
2850
+ */
2851
+ "onMrdNavigate"?: (event: MrdMemoContainerCustomEvent<{ href?: string; label: string }>) => void;
2788
2852
  /**
2789
2853
  * Quick-edit submit. Host PATCHes `href` with `values`, same as mrd-document-list's drag-move.
2790
2854
  */
@@ -2799,6 +2863,11 @@ declare namespace LocalJSX {
2799
2863
  * @default false
2800
2864
  */
2801
2865
  "readOnly"?: boolean;
2866
+ /**
2867
+ * True unless this is a container-scoped RELATED_VIEW (a company's own memo tab, say) where every card's container is obviously the page you're already on — forwarded to mrd-memo-list to show/hide its per-card container link. A top-level VIEW or an author-scoped RELATED_VIEW both still need it, since the container isn't implied by the page context.
2868
+ * @default true
2869
+ */
2870
+ "showContainerLink"?: boolean;
2802
2871
  /**
2803
2872
  * Lookup key used for the embedded `data-view` attribute.
2804
2873
  * @default ''
@@ -2846,6 +2915,10 @@ declare namespace LocalJSX {
2846
2915
  * Fired when a page needs fetching; same shape as mrd-table's mrdLoadPage minus `qs`'s column-filter support (cards have no filter UI) — host calls setPage() with the result.
2847
2916
  */
2848
2917
  "onMrdLoadPage"?: (event: MrdMemoListCustomEvent<{ page: number; sort: string; path: string; qs: string }>) => void;
2918
+ /**
2919
+ * The container link on a card was clicked — this is real navigation (to the container record), unrelated to mrdEdit.
2920
+ */
2921
+ "onMrdNavigate"?: (event: MrdMemoListCustomEvent<{ href?: string; label: string }>) => void;
2849
2922
  /**
2850
2923
  * Records per page (must match API page size).
2851
2924
  * @default 20
@@ -2861,6 +2934,11 @@ declare namespace LocalJSX {
2861
2934
  * @default false
2862
2935
  */
2863
2936
  "readOnly"?: boolean;
2937
+ /**
2938
+ * False when the list is already scoped to its own container (a company's own memo tab) — showing "belongs to: <this same company>" on every card there would be redundant. True everywhere else (top-level VIEW, or a RELATED_VIEW scoped by a different relation, e.g. a person's authored-memos list).
2939
+ * @default true
2940
+ */
2941
+ "showContainerLink"?: boolean;
2864
2942
  }
2865
2943
  /**
2866
2944
  * Archetype-driven single-memo view. Given a `commons.memo` binding and a data
@@ -3067,6 +3145,10 @@ declare namespace LocalJSX {
3067
3145
  "value"?: string;
3068
3146
  }
3069
3147
  interface MrdTable {
3148
+ /**
3149
+ * Whether the current user may create a record for the table's bound route. Leave `undefined` for standalone use — the table then asks on its own via mrdCheckCapabilities and hides the create button until setCanCreate() answers. Set it explicitly when a host already knows the answer (e.g. mrd-layout-section, which asks once per binding and hands the answer to whichever body it mounts) — the table then trusts it directly and never asks on its own (TASK-0299).
3150
+ */
3151
+ "canCreate"?: boolean;
3070
3152
  /**
3071
3153
  * The VIEW or RELATED_VIEW layout item. Contains view config, dataClass, fromClass, actions etc.
3072
3154
  * @default null
@@ -3080,6 +3162,10 @@ declare namespace LocalJSX {
3080
3162
  * Fired when a toolbar action button is clicked. For 'export': includes `path` (relative excel path) and `qs` (current sort+filter params). For 'create': includes `dataClass` (target type) and `parentPath` (e.g. /buyers/123 for RELATED_VIEW).
3081
3163
  */
3082
3164
  "onMrdAction"?: (event: MrdTableCustomEvent<{ action: string; path?: string; qs?: string; dataClass?: string; parentPath?: string | null; basicType?: string }>) => void;
3165
+ /**
3166
+ * Standalone use only (never fires while the `canCreate` prop is set — see there). Fired once per table binding (initial load, and whenever the bound item, parent record or active view changes) to ask the host whether the current user may create a record here. Carries the same route the table already uses for its own rows, unconstructed — VIEW: GET /data/{tenant}/{type}/capabilities; RELATED_VIEW: GET /data/{tenant}/{refType}/{refId}/{type}/capabilities. `filterClass`, when the view declares one, is the same subtype the row fetch sends as `?type=` — e.g. a "contents" RELATED_VIEW filtered to `document` asks specifically whether a document may be created here, not any content type. The add button stays hidden until the host calls setCanCreate() (FINDING-0155 / TASK-0299).
3167
+ */
3168
+ "onMrdCheckCapabilities"?: (event: MrdTableCustomEvent<{ type: string; refType?: string; refId?: string; filterClass?: string }>) => void;
3083
3169
  /**
3084
3170
  * Fired when a FILE or IMAGE cell is clicked. Host resolves the href to a signed download URL.
3085
3171
  */
@@ -3277,6 +3363,7 @@ declare namespace LocalJSX {
3277
3363
  "height": number;
3278
3364
  "locale": string;
3279
3365
  "readOnly": boolean;
3366
+ "mayCreate": boolean;
3280
3367
  }
3281
3368
  interface MrdDocumentListAttributes {
3282
3369
  "parentId": string;
@@ -3366,15 +3453,19 @@ declare namespace LocalJSX {
3366
3453
  interface MrdMemoContainerAttributes {
3367
3454
  "parentId": string;
3368
3455
  "containerHref": string;
3456
+ "containerRelated": boolean;
3457
+ "showContainerLink": boolean;
3369
3458
  "viewKey": string;
3370
3459
  "locale": string;
3371
3460
  "readOnly": boolean;
3461
+ "canCreate": boolean;
3372
3462
  }
3373
3463
  interface MrdMemoListAttributes {
3374
3464
  "parentId": string;
3375
3465
  "pageSize": number;
3376
3466
  "locale": string;
3377
3467
  "readOnly": boolean;
3468
+ "showContainerLink": boolean;
3378
3469
  }
3379
3470
  interface MrdMemoViewAttributes {
3380
3471
  "locale": string;
@@ -3429,6 +3520,7 @@ declare namespace LocalJSX {
3429
3520
  "tableHeight": number;
3430
3521
  "requestTimeoutMs": number;
3431
3522
  "readOnly": boolean;
3523
+ "canCreate": boolean;
3432
3524
  }
3433
3525
  interface MrdTextFieldAttributes {
3434
3526
  "name": string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmlogic/components",
3
- "version": "0.5.15",
3
+ "version": "0.5.17",
4
4
  "description": "Stencil.js web component library for dynamic forms and virtual-scroll data tables",
5
5
  "license": "MIT",
6
6
  "author": "Mosterd",