@mmlogic/components 0.5.17 → 0.5.18

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/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 +98 -13
  4. package/dist/collection/components/layout/mrd-layout-section/mrd-layout-section.js +77 -11
  5. package/dist/collection/components/table/mrd-table/mrd-table.js +94 -8
  6. package/dist/collection/dev/api.js +3 -1
  7. package/dist/collection/dev/app.js +42 -3
  8. package/dist/components/mrd-layout-section.js +1 -1
  9. package/dist/components/mrd-table2.js +1 -1
  10. package/dist/esm/loader.js +1 -1
  11. package/dist/esm/mosterdcomponents.js +1 -1
  12. package/dist/esm/mrd-boolean-field_28.entry.js +98 -13
  13. package/dist/mosterdcomponents/cell-renderer-CMUxFREW.js.map +1 -0
  14. package/dist/mosterdcomponents/client-layout-BJkVeSq6.js.map +1 -0
  15. package/dist/mosterdcomponents/document-attachments-BufPmMRv.js.map +1 -0
  16. package/dist/mosterdcomponents/field-helpers-BWAp5fD8.js.map +1 -0
  17. package/dist/mosterdcomponents/file-upload-common-DDWuC9-3.js.map +1 -0
  18. package/dist/mosterdcomponents/format-gcecItcD.js.map +1 -0
  19. package/dist/mosterdcomponents/i18n-OzbszktW.js.map +1 -0
  20. package/dist/mosterdcomponents/index-1ayBojyN.js.map +1 -0
  21. package/dist/mosterdcomponents/index-CkcFwdPc.js.map +1 -0
  22. package/dist/mosterdcomponents/index.esm.js.map +1 -0
  23. package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
  24. package/dist/mosterdcomponents/mosterdcomponents.esm.js.map +1 -0
  25. package/dist/mosterdcomponents/p-29d6dcbc.entry.js +3 -0
  26. package/dist/mosterdcomponents/purify.es-_duHfPgC.js.map +1 -0
  27. package/dist/mosterdcomponents/query-params-3TXd5CUO.js.map +1 -0
  28. package/dist/mosterdcomponents/quill-C9pgw_k-.js.map +1 -0
  29. package/dist/mosterdcomponents/table-query-DJq1uKqJ.js.map +1 -0
  30. package/dist/mosterdcomponents/validation-B_0Lx9DE.js.map +1 -0
  31. package/dist/types/components/layout/mrd-layout-section/mrd-layout-section.d.ts +24 -2
  32. package/dist/types/components/table/mrd-table/mrd-table.d.ts +33 -3
  33. package/dist/types/components.d.ts +34 -4
  34. package/package.json +1 -1
  35. package/dist/mosterdcomponents/p-f72668e9.entry.js +0 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-query-DJq1uKqJ.js","sources":["src/components/table/mrd-table/table-query.ts"],"sourcesContent":["import { ColumnFilter, TableColumn } from '../../../utils/cell-renderer';\nimport { ViewFilter } from '../../../types/client-layout';\nimport { applyViewFilters } from '../../../utils/query-params';\n\n/**\n * Pure sort/filter/aggregation query logic for mrd-table.\n * No component state — everything is passed in.\n */\n\nexport const TEXT_TYPES = new Set(['TEXT', 'TEXTBLOCK', 'EMAIL', 'HYPERLINK']);\nexport const NUMERIC_TYPES = new Set(['INTEGER', 'DECIMAL', 'PERCENTAGE', 'CURRENCY']);\nexport const DATE_TYPES = new Set(['DATE', 'DATETIME', 'TIME']);\nexport const NO_FILTER_TYPES = new Set(['FILE', 'IMAGE']);\n\n/** Column types that cannot be sorted or filtered (not stored in PostgreSQL). */\nexport const NON_INTERACTIVE_TYPES = new Set(['LONGTEXT', 'JSON', 'FILE', 'IMAGE']);\n\n/** Wait this long (ms) after the user stops typing in the free-text search box\n * before firing the search request — mirrors REQUEST_DEBOUNCE_MS's purpose\n * (skip intermediate keystrokes) but is tuned for typing, not scrolling. */\nexport const SEARCH_DEBOUNCE_MS = 400;\n\nexport function parseDefaultSort(defaultSort: string): { field: string; dir: 'asc' | 'desc' } {\n if (!defaultSort) return { field: '', dir: 'asc' };\n const parts = defaultSort.split(',');\n return { field: parts[0].trim(), dir: parts[1]?.trim() === 'desc' ? 'desc' : 'asc' };\n}\n\n/** Raw sort query-param value, e.g. \"name\" or \"name,desc\". */\nexport function buildSortParam(field: string, dir: 'asc' | 'desc'): string {\n if (!field) return '';\n return dir === 'desc' ? `${field},desc` : field;\n}\n\n/** Query params for a page request: page + sort + filterClass + view filters + active column filters. */\nexport function buildTableQueryParams(opts: {\n page: number;\n sort: string;\n filterClass?: string | null;\n viewFilters?: ViewFilter[] | null;\n activeFilters: Iterable<ColumnFilter>;\n /** Free-text search query from the toolbar's search box (VIEW only). */\n query?: string;\n}): string {\n const p = new URLSearchParams();\n if (opts.page > 0) p.set('page', String(opts.page));\n if (opts.sort) p.set('sort', opts.sort);\n if (opts.filterClass) p.set('type', opts.filterClass);\n applyViewFilters(p, opts.viewFilters);\n if (opts.query) p.set('q', opts.query);\n for (const f of opts.activeFilters) {\n if (f.operator === 'isEmpty') { p.set(f.field, ''); continue; }\n if (f.operator === 'isNotEmpty') { p.set(f.field + '_notempty', 'true'); continue; }\n if (f.operator === 'startsWith') { p.set(f.field + '_startswith', String(f.value ?? '')); continue; }\n if (f.values?.length) { p.set(f.field, f.values.join(',')); continue; }\n if (f.value != null) p.set(f.field, String(f.value));\n if (f.from != null) p.set(f.field + '_from', String(f.from));\n if (f.to != null) p.set(f.field + '_to', String(f.to));\n }\n return p.toString();\n}\n\n/** Groups aggregate columns by function; null when the view has no aggregates. */\nexport function buildAggregationParams(columns: TableColumn[]): { sum?: string[]; avg?: string[]; count?: string[] } | null {\n const groups: { sum: string[]; avg: string[]; count: string[] } = { sum: [], avg: [], count: [] };\n for (const col of columns) {\n if (col.type !== 'FIELD' || !col.aggregate) continue;\n const fn = col.aggregate.toLowerCase() as 'sum' | 'avg' | 'count';\n if (fn in groups) groups[fn].push(col.name ?? '');\n }\n const params: { sum?: string[]; avg?: string[]; count?: string[] } = {};\n if (groups.sum.length) params.sum = groups.sum;\n if (groups.avg.length) params.avg = groups.avg;\n if (groups.count.length) params.count = groups.count;\n return Object.keys(params).length > 0 ? params : null;\n}\n\n/** Aggregation query string: the page-0 query params without page/sort, plus sum/avg/count. */\nexport function buildAggregationQs(basePageQs: string, columns: TableColumn[]): string {\n const p = new URLSearchParams(basePageQs);\n p.delete('page');\n p.delete('sort');\n const groups = buildAggregationParams(columns);\n if (groups?.sum?.length) p.set('sum', groups.sum.join(','));\n if (groups?.avg?.length) p.set('avg', groups.avg.join(','));\n if (groups?.count?.length) p.set('count', groups.count.join(','));\n return p.toString();\n}\n\n/** True when the pending filter actually constrains anything. */\nexport function filterHasValue(f: Partial<ColumnFilter>): boolean {\n if (f.operator === 'isEmpty' || f.operator === 'isNotEmpty') return true;\n if (f.values !== undefined && f.values.length > 0) return true;\n if (f.value != null && f.value !== '') return true;\n if (typeof f.value === 'boolean') return true;\n if (f.from != null && f.from !== '') return true;\n if (f.to != null && f.to !== '') return true;\n return false;\n}\n\n// ── DATETIME filters: the user edits local \"YYYY-MM-DD\" dates, the API stores UTC ISO ──\n\n/** UTC ISO string at the start (midnight) of the given local day. */\nexport function dateLocalToUTCStart(dateStr: string): string {\n if (!dateStr) return dateStr;\n const [year, month, day] = dateStr.split('-').map(Number);\n return new Date(year, month - 1, day).toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n}\n\n/** Start of the day AFTER the given local date (exclusive range end). */\nexport function dateLocalToUTCEndExclusive(dateStr: string): string {\n if (!dateStr) return dateStr;\n const [year, month, day] = dateStr.split('-').map(Number);\n return new Date(year, month - 1, day + 1).toISOString().replace(/\\.\\d{3}Z$/, 'Z');\n}\n\n/** Stored UTC ISO string back to the local \"YYYY-MM-DD\" date. */\nexport function utcISOToLocalDate(utcStr: string): string {\n if (!utcStr) return utcStr;\n const d = new Date(utcStr);\n if (isNaN(d.getTime())) return utcStr;\n return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;\n}\n\n/** The stored \"to\" is the exclusive end (next midnight); subtract a day to recover the entered date. */\nexport function utcISOToLocalDateExclusiveEnd(utcStr: string): string {\n if (!utcStr) return utcStr;\n const d = new Date(utcStr);\n if (isNaN(d.getTime())) return utcStr;\n d.setDate(d.getDate() - 1);\n return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;\n}\n\n/** Applies the local→UTC conversion when a DATETIME filter is submitted.\n * Exact date → range covering the full local day. */\nexport function normalizeDatetimeFilter(f: Partial<ColumnFilter>): Partial<ColumnFilter> {\n const normalized = { ...f };\n if (f.dataType === 'DATETIME' && f.operator !== 'isEmpty' && f.operator !== 'isNotEmpty') {\n if (typeof normalized.value === 'string' && normalized.value) {\n normalized.from = dateLocalToUTCStart(normalized.value);\n normalized.to = dateLocalToUTCEndExclusive(normalized.value);\n normalized.value = undefined;\n } else {\n if (typeof normalized.from === 'string' && normalized.from)\n normalized.from = dateLocalToUTCStart(normalized.from);\n if (typeof normalized.to === 'string' && normalized.to)\n normalized.to = dateLocalToUTCEndExclusive(normalized.to);\n }\n }\n return normalized;\n}\n\n/** Converts a stored DATETIME filter back to local dates for the popup.\n * A range covering a single local day is restored to exact-date mode. */\nexport function datetimeFilterToDisplay(existing: ColumnFilter): Partial<ColumnFilter> {\n const display: Partial<ColumnFilter> = { ...existing };\n if (typeof display.from === 'string' && display.from)\n display.from = utcISOToLocalDate(display.from);\n if (typeof display.to === 'string' && display.to)\n display.to = utcISOToLocalDateExclusiveEnd(display.to);\n if (display.from && display.to && display.from === display.to) {\n return { ...display, value: display.from, from: undefined, to: undefined };\n }\n return display;\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-B_0Lx9DE.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;;;;"}
@@ -22,6 +22,12 @@ export declare class MrdLayoutSection {
22
22
  * create ("+") action and the documents view's New folder / Upload are disabled
23
23
  * with a tooltip explaining why, so it's clear at a glance the user can't mutate data. */
24
24
  readOnly: boolean;
25
+ /** When false, skips the mrdViewCheckCapabilities round trip for every VIEW/RELATED_VIEW
26
+ * binding and hands mrd-table/mrd-memo-container/mrd-document-container their create
27
+ * affordance as allowed immediately — for a tenant with no access control configured,
28
+ * the answer would always be mayCreate: true anyway (FINDING-0171 / TASK-0322). Default
29
+ * `true` keeps today's ask-and-hide behaviour unchanged. */
30
+ accessControlEnabled: boolean;
25
31
  /** The active account's linked person record (userProfile.links.person), if any.
26
32
  * Threaded to mrd-memo-container so a top-level memo VIEW (no parent record to
27
33
  * attach a new memo to) can still offer "New memo" by falling back to the
@@ -38,6 +44,12 @@ export declare class MrdLayoutSection {
38
44
  * means "not answered yet" and is treated as false (hidden), same default as mrd-table's
39
45
  * own standalone behaviour (TASK-0299). */
40
46
  private canCreateMap;
47
+ /** Companion to canCreateMap — concrete types the mrdViewCheckCapabilities answer allows,
48
+ * when the API reports them; passed to mrd-table's `allowedTypes` prop to narrow its
49
+ * create-type picker down to types a create POST would actually accept (FINDING-0176 /
50
+ * TASK-0314). A missing entry means "not answered yet / not reported" — mrd-table then
51
+ * leaves `item.createTypes` unfiltered, same as before this existed. */
52
+ private allowedTypesMap;
41
53
  private historyClickOutside;
42
54
  /** Signature last asked per view key (see emitCapabilitiesChecks()) — avoids re-emitting
43
55
  * mrdViewCheckCapabilities on every data/items update when the binding hasn't changed. */
@@ -113,7 +125,9 @@ export declare class MrdLayoutSection {
113
125
  /** Emitted once per VIEW/RELATED_VIEW binding — computed here directly, not relayed from a
114
126
  * child (see emitCapabilitiesChecks()), so it covers mrd-table, mrd-memo-container and
115
127
  * mrd-document-container uniformly. `name` is the view key (viewKeyFor(item)) — pass it
116
- * back to setViewCanCreate() to answer it. */
128
+ * back to setViewCanCreate() to answer it. setViewCanCreate()'s optional third argument
129
+ * narrows a table's `item.createTypes` picker to the concrete types the answer allows,
130
+ * when the API's capabilities response reports them (FINDING-0176 / TASK-0314). */
117
131
  mrdViewCheckCapabilities: EventEmitter<{
118
132
  name: string;
119
133
  type: string;
@@ -188,7 +202,15 @@ export declare class MrdLayoutSection {
188
202
  * canCreateMap and passed down as a plain prop to whichever body is mounted for that key
189
203
  * (mrd-table, mrd-memo-container or mrd-document-container) — no DOM lookup needed, unlike
190
204
  * setViewPage/setViewAggregations, since the prop flows through the next render. */
191
- setViewCanCreate(name: string, value: boolean): Promise<void>;
205
+ setViewCanCreate(name: string, value: boolean, allowedTypes?: string[]): Promise<void>;
206
+ /** `canCreateMap[key]` when access control is configured (default); always allowed
207
+ * when `accessControlEnabled` is false, since emitCapabilitiesChecks() never asked
208
+ * and canCreateMap[key] would otherwise stay permanently unanswered. */
209
+ private effectiveCanCreate;
210
+ /** `allowedTypesMap[key]` when access control is configured; `undefined` (don't filter)
211
+ * when disabled, since emitCapabilitiesChecks() never asked and the map entry would
212
+ * otherwise stay permanently unanswered — see effectiveCanCreate(). */
213
+ private effectiveAllowedTypes;
192
214
  /** Inject distinct values into an embedded mrd-document-list for a document view. */
193
215
  setViewDistinct(name: string, nodeId: string, values: DistinctValue[]): Promise<void>;
194
216
  /** Inject the uploaded file reference for a dropped file, so the document view
@@ -70,6 +70,21 @@ export declare class MrdTable {
70
70
  * the answer to whichever body it mounts) — the table then trusts it directly and never
71
71
  * asks on its own (TASK-0299). */
72
72
  canCreate?: boolean;
73
+ /** Concrete types (`item.createTypes[].type`) the current user may actually create, when
74
+ * `item.createTypes` offers a picker for a family type — narrows it down to only the types
75
+ * a create POST would accept (FINDING-0176 / TASK-0314). Leave `undefined` for standalone
76
+ * use — the table takes it from the second argument of setCanCreate() alongside `canCreate`.
77
+ * Set it explicitly (e.g. from mrd-layout-section, alongside `canCreate`) when the host
78
+ * already has the answer. `undefined` (not yet answered, or an older host/API that doesn't
79
+ * report it) means "don't filter" — `item.createTypes` is shown unfiltered, same as before
80
+ * this existed. */
81
+ allowedTypes?: string[] | null;
82
+ /** When false, skips the standalone mrdCheckCapabilities round trip entirely and renders
83
+ * the create action immediately as allowed — for a tenant that has no access control
84
+ * configured, the answer would always be true anyway (FINDING-0171 / TASK-0322). Ignored
85
+ * while `canCreate` is set explicitly (the host already controls the answer directly in
86
+ * that mode). Default `true` keeps today's ask-and-hide behaviour unchanged. */
87
+ accessControlEnabled: boolean;
73
88
  /** Clamp renderEnd when totalElements shrinks (e.g. after a filter is applied).
74
89
  * 0 means "unknown" (hosts that rely on minKnownTotal never set it, and some reset it
75
90
  * while a filter is being applied) — clamping to it would collapse the window to a
@@ -132,6 +147,9 @@ export declare class MrdTable {
132
147
  * hidden (TASK-0299) until the host answers mrdCheckCapabilities via setCanCreate(). Ignored
133
148
  * when the host controls `canCreate` directly; see effectiveCanCreate(). */
134
149
  private selfCanCreate;
150
+ /** Self-asked companion to selfCanCreate — the concrete types setCanCreate() reported allowed,
151
+ * or `undefined` while unanswered / when the host's mrdCheckCapabilities answer omitted it. */
152
+ private selfAllowedTypes;
135
153
  /** Fired when a page needs to be fetched. Host fetches and calls setPage().
136
154
  * `sort` is the raw query-param value, e.g. "name" or "name,desc". */
137
155
  mrdLoadPage: EventEmitter<{
@@ -184,7 +202,10 @@ export declare class MrdTable {
184
202
  * `filterClass`, when the view declares one, is the same subtype the row fetch sends as
185
203
  * `?type=` — e.g. a "contents" RELATED_VIEW filtered to `document` asks specifically whether
186
204
  * 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). */
205
+ * The add button stays hidden until the host calls setCanCreate() (FINDING-0155 / TASK-0299).
206
+ * setCanCreate()'s optional second argument narrows `item.createTypes`'s picker down to the
207
+ * concrete types the answer allows, when the API's capabilities response reports them
208
+ * (FINDING-0176 / TASK-0314). */
188
209
  mrdCheckCapabilities: EventEmitter<{
189
210
  type: string;
190
211
  refType?: string;
@@ -219,7 +240,7 @@ export declare class MrdTable {
219
240
  * prop is set, since the host controls it directly in that mode). Call it any time after
220
241
  * the event fires; a stale answer for an old binding is discarded automatically
221
242
  * (selfCanCreate is reset to false before every new mrdCheckCapabilities emission). */
222
- setCanCreate(value: boolean): Promise<void>;
243
+ setCanCreate(value: boolean, allowedTypes?: string[]): Promise<void>;
223
244
  disconnectedCallback(): void;
224
245
  componentDidRender(): void;
225
246
  /** Freeze the column widths once the first data page has rendered.
@@ -334,8 +355,17 @@ export declare class MrdTable {
334
355
  * mode must not flip back to the rows prop (and its "no results") while page 0 is in flight. */
335
356
  private get isPaginated();
336
357
  private get columns();
337
- /** `canCreate` when the host controls it directly, else the table's own self-asked answer. */
358
+ /** `canCreate` when the host controls it directly; else, when access control is disabled,
359
+ * always allowed; else the table's own self-asked answer. */
338
360
  private get effectiveCanCreate();
361
+ /** `allowedTypes` when the host controls it directly, else the table's own self-asked
362
+ * answer. `undefined` means "unknown — don't filter", not "nothing allowed". */
363
+ private get effectiveAllowedTypes();
364
+ /** `item.createTypes` intersected with effectiveAllowedTypes when that is known, so the
365
+ * create-type picker only offers concrete types a create POST would actually accept
366
+ * (FINDING-0176 / TASK-0314). Unfiltered when the answer isn't known (undefined) — an
367
+ * older host/API that never reports allowedTypes keeps today's unfiltered behaviour. */
368
+ private get effectiveCreateTypes();
339
369
  private get tableActions();
340
370
  private toggleCreatePicker;
341
371
  private closeCreatePicker;
@@ -521,6 +521,11 @@ export namespace Components {
521
521
  "statusListItems": ClientListValue[] | null;
522
522
  }
523
523
  interface MrdLayoutSection {
524
+ /**
525
+ * When false, skips the mrdViewCheckCapabilities round trip for every VIEW/RELATED_VIEW binding and hands mrd-table/mrd-memo-container/mrd-document-container their create affordance as allowed immediately — for a tenant with no access control configured, the answer would always be mayCreate: true anyway (FINDING-0171 / TASK-0322). Default `true` keeps today's ask-and-hide behaviour unchanged.
526
+ * @default true
527
+ */
528
+ "accessControlEnabled": boolean;
524
529
  /**
525
530
  * Top-level archetypes on the object dashboard. When it contains commons.document, the record is rendered as a single-document view instead of generic fields.
526
531
  * @default []
@@ -574,7 +579,7 @@ export namespace Components {
574
579
  /**
575
580
  * 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
581
  */
577
- "setViewCanCreate": (name: string, value: boolean) => Promise<void>;
582
+ "setViewCanCreate": (name: string, value: boolean, allowedTypes?: string[]) => Promise<void>;
578
583
  /**
579
584
  * 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.
580
585
  */
@@ -1011,6 +1016,15 @@ export namespace Components {
1011
1016
  "value": string;
1012
1017
  }
1013
1018
  interface MrdTable {
1019
+ /**
1020
+ * When false, skips the standalone mrdCheckCapabilities round trip entirely and renders the create action immediately as allowed — for a tenant that has no access control configured, the answer would always be true anyway (FINDING-0171 / TASK-0322). Ignored while `canCreate` is set explicitly (the host already controls the answer directly in that mode). Default `true` keeps today's ask-and-hide behaviour unchanged.
1021
+ * @default true
1022
+ */
1023
+ "accessControlEnabled": boolean;
1024
+ /**
1025
+ * Concrete types (`item.createTypes[].type`) the current user may actually create, when `item.createTypes` offers a picker for a family type — narrows it down to only the types a create POST would accept (FINDING-0176 / TASK-0314). Leave `undefined` for standalone use — the table takes it from the second argument of setCanCreate() alongside `canCreate`. Set it explicitly (e.g. from mrd-layout-section, alongside `canCreate`) when the host already has the answer. `undefined` (not yet answered, or an older host/API that doesn't report it) means "don't filter" — `item.createTypes` is shown unfiltered, same as before this existed.
1026
+ */
1027
+ "allowedTypes"?: string[] | null;
1014
1028
  /**
1015
1029
  * 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
1030
  */
@@ -1065,7 +1079,7 @@ export namespace Components {
1065
1079
  /**
1066
1080
  * 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
1081
  */
1068
- "setCanCreate": (value: boolean) => Promise<void>;
1082
+ "setCanCreate": (value: boolean, allowedTypes?: string[]) => Promise<void>;
1069
1083
  /**
1070
1084
  * 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).
1071
1085
  */
@@ -2617,6 +2631,11 @@ declare namespace LocalJSX {
2617
2631
  "statusListItems"?: ClientListValue[] | null;
2618
2632
  }
2619
2633
  interface MrdLayoutSection {
2634
+ /**
2635
+ * When false, skips the mrdViewCheckCapabilities round trip for every VIEW/RELATED_VIEW binding and hands mrd-table/mrd-memo-container/mrd-document-container their create affordance as allowed immediately — for a tenant with no access control configured, the answer would always be mayCreate: true anyway (FINDING-0171 / TASK-0322). Default `true` keeps today's ask-and-hide behaviour unchanged.
2636
+ * @default true
2637
+ */
2638
+ "accessControlEnabled"?: boolean;
2620
2639
  /**
2621
2640
  * Top-level archetypes on the object dashboard. When it contains commons.document, the record is rendered as a single-document view instead of generic fields.
2622
2641
  * @default []
@@ -2689,7 +2708,7 @@ declare namespace LocalJSX {
2689
2708
  */
2690
2709
  "onMrdViewAction"?: (event: MrdLayoutSectionCustomEvent<{ name: string; action: string; dataClass: string; path?: string; qs?: string; parentPath?: string | null; basicType?: string }>) => void;
2691
2710
  /**
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.
2711
+ * 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. setViewCanCreate()'s optional third argument narrows a table's `item.createTypes` picker to the concrete types the answer allows, when the API's capabilities response reports them (FINDING-0176 / TASK-0314).
2693
2712
  */
2694
2713
  "onMrdViewCheckCapabilities"?: (event: MrdLayoutSectionCustomEvent<{ name: string; type: string; refType?: string; refId?: string; filterClass?: string }>) => void;
2695
2714
  /**
@@ -3145,6 +3164,15 @@ declare namespace LocalJSX {
3145
3164
  "value"?: string;
3146
3165
  }
3147
3166
  interface MrdTable {
3167
+ /**
3168
+ * When false, skips the standalone mrdCheckCapabilities round trip entirely and renders the create action immediately as allowed — for a tenant that has no access control configured, the answer would always be true anyway (FINDING-0171 / TASK-0322). Ignored while `canCreate` is set explicitly (the host already controls the answer directly in that mode). Default `true` keeps today's ask-and-hide behaviour unchanged.
3169
+ * @default true
3170
+ */
3171
+ "accessControlEnabled"?: boolean;
3172
+ /**
3173
+ * Concrete types (`item.createTypes[].type`) the current user may actually create, when `item.createTypes` offers a picker for a family type — narrows it down to only the types a create POST would accept (FINDING-0176 / TASK-0314). Leave `undefined` for standalone use — the table takes it from the second argument of setCanCreate() alongside `canCreate`. Set it explicitly (e.g. from mrd-layout-section, alongside `canCreate`) when the host already has the answer. `undefined` (not yet answered, or an older host/API that doesn't report it) means "don't filter" — `item.createTypes` is shown unfiltered, same as before this existed.
3174
+ */
3175
+ "allowedTypes"?: string[] | null;
3148
3176
  /**
3149
3177
  * 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
3178
  */
@@ -3163,7 +3191,7 @@ declare namespace LocalJSX {
3163
3191
  */
3164
3192
  "onMrdAction"?: (event: MrdTableCustomEvent<{ action: string; path?: string; qs?: string; dataClass?: string; parentPath?: string | null; basicType?: string }>) => void;
3165
3193
  /**
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).
3194
+ * 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). setCanCreate()'s optional second argument narrows `item.createTypes`'s picker down to the concrete types the answer allows, when the API's capabilities response reports them (FINDING-0176 / TASK-0314).
3167
3195
  */
3168
3196
  "onMrdCheckCapabilities"?: (event: MrdTableCustomEvent<{ type: string; refType?: string; refId?: string; filterClass?: string }>) => void;
3169
3197
  /**
@@ -3431,6 +3459,7 @@ declare namespace LocalJSX {
3431
3459
  interface MrdLayoutSectionAttributes {
3432
3460
  "locale": string;
3433
3461
  "readOnly": boolean;
3462
+ "accessControlEnabled": boolean;
3434
3463
  }
3435
3464
  interface MrdListFieldAttributes {
3436
3465
  "name": string;
@@ -3521,6 +3550,7 @@ declare namespace LocalJSX {
3521
3550
  "requestTimeoutMs": number;
3522
3551
  "readOnly": boolean;
3523
3552
  "canCreate": boolean;
3553
+ "accessControlEnabled": boolean;
3524
3554
  }
3525
3555
  interface MrdTextFieldAttributes {
3526
3556
  "name": string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmlogic/components",
3
- "version": "0.5.17",
3
+ "version": "0.5.18",
4
4
  "description": "Stencil.js web component library for dynamic forms and virtual-scroll data tables",
5
5
  "license": "MIT",
6
6
  "author": "Mosterd",