@mmlogic/components 0.4.0 → 0.4.2

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 (92) hide show
  1. package/dist/cjs/index.cjs.js +8 -0
  2. package/dist/cjs/loader.cjs.js +1 -1
  3. package/dist/cjs/mosterdcomponents.cjs.js +1 -1
  4. package/dist/cjs/{mrd-boolean-field_23.cjs.entry.js → mrd-boolean-field_24.cjs.entry.js} +348 -39
  5. package/dist/collection/collection-manifest.json +1 -0
  6. package/dist/collection/components/documents/mrd-document-container/mrd-document-container.css +14 -1
  7. package/dist/collection/components/documents/mrd-document-container/mrd-document-container.js +22 -7
  8. package/dist/collection/components/documents/mrd-document-list/mrd-document-list.css +8 -5
  9. package/dist/collection/components/documents/mrd-document-list/tree-view.js +13 -1
  10. package/dist/collection/components/documents/mrd-document-view/mrd-document-view.css +39 -29
  11. package/dist/collection/components/documents/mrd-document-view/mrd-document-view.js +109 -8
  12. package/dist/collection/components/documents/mrd-file-preview/file-preview-kind.js +30 -0
  13. package/dist/collection/components/documents/mrd-file-preview/mrd-file-preview.css +59 -0
  14. package/dist/collection/components/documents/mrd-file-preview/mrd-file-preview.js +212 -0
  15. package/dist/collection/components/fields/mrd-boolean-field/mrd-boolean-field.js +1 -1
  16. package/dist/collection/components/fields/mrd-currency-field/mrd-currency-field.js +1 -1
  17. package/dist/collection/components/fields/mrd-date-field/mrd-date-field.js +1 -1
  18. package/dist/collection/components/fields/mrd-datetime-field/mrd-datetime-field.js +1 -1
  19. package/dist/collection/components/fields/mrd-email-field/mrd-email-field.js +1 -1
  20. package/dist/collection/components/fields/mrd-file-field/mrd-file-field.js +1 -1
  21. package/dist/collection/components/fields/mrd-image-field/mrd-image-field.js +1 -1
  22. package/dist/collection/components/fields/mrd-longtext-field/mrd-longtext-field.js +1 -1
  23. package/dist/collection/components/fields/mrd-number-field/mrd-number-field.js +1 -1
  24. package/dist/collection/components/fields/mrd-secret-field/mrd-secret-field.js +2 -2
  25. package/dist/collection/components/fields/mrd-text-field/mrd-text-field.js +1 -1
  26. package/dist/collection/components/fields/mrd-textarea-field/mrd-textarea-field.js +1 -1
  27. package/dist/collection/components/fields/mrd-time-field/mrd-time-field.js +1 -1
  28. package/dist/collection/components/layout/mrd-layout-section/mrd-layout-section.css +5 -0
  29. package/dist/collection/components/layout/mrd-layout-section/mrd-layout-section.js +91 -8
  30. package/dist/collection/components/table/mrd-table/mrd-table.css +20 -0
  31. package/dist/collection/components/table/mrd-table/mrd-table.js +124 -5
  32. package/dist/collection/components/table/mrd-table/virtual-scroll.js +14 -0
  33. package/dist/collection/dev/api.js +9 -0
  34. package/dist/collection/dev/app.js +101 -3
  35. package/dist/collection/dev/example-data.js +24 -0
  36. package/dist/collection/types/client-layout.js +8 -0
  37. package/dist/collection/utils/i18n.js +40 -0
  38. package/dist/components/client-layout.js +1 -1
  39. package/dist/components/i18n.js +1 -1
  40. package/dist/components/index.js +1 -1
  41. package/dist/components/mrd-boolean-field2.js +1 -1
  42. package/dist/components/mrd-currency-field2.js +1 -1
  43. package/dist/components/mrd-date-field2.js +1 -1
  44. package/dist/components/mrd-datetime-field2.js +1 -1
  45. package/dist/components/mrd-document-container2.js +1 -1
  46. package/dist/components/mrd-document-list2.js +1 -1
  47. package/dist/components/mrd-document-view2.js +1 -1
  48. package/dist/components/mrd-email-field2.js +1 -1
  49. package/dist/components/mrd-file-field2.js +1 -1
  50. package/dist/components/mrd-file-preview.d.ts +11 -0
  51. package/dist/components/mrd-file-preview.js +1 -0
  52. package/dist/components/mrd-file-preview2.js +1 -0
  53. package/dist/components/mrd-image-field2.js +1 -1
  54. package/dist/components/mrd-layout-section.js +1 -1
  55. package/dist/components/mrd-longtext-field2.js +1 -1
  56. package/dist/components/mrd-number-field2.js +1 -1
  57. package/dist/components/mrd-secret-field2.js +1 -1
  58. package/dist/components/mrd-table2.js +1 -1
  59. package/dist/components/mrd-text-field2.js +1 -1
  60. package/dist/components/mrd-textarea-field2.js +1 -1
  61. package/dist/components/mrd-time-field2.js +1 -1
  62. package/dist/esm/index.js +9 -1
  63. package/dist/esm/loader.js +1 -1
  64. package/dist/esm/mosterdcomponents.js +1 -1
  65. package/dist/esm/{mrd-boolean-field_23.entry.js → mrd-boolean-field_24.entry.js} +349 -41
  66. package/dist/mosterdcomponents/cell-renderer-PbcEU4ph.js.map +1 -0
  67. package/dist/mosterdcomponents/client-layout-DCOAAH92.js.map +1 -0
  68. package/dist/mosterdcomponents/field-helpers-CASS3akr.js.map +1 -0
  69. package/dist/mosterdcomponents/file-upload-common-D1ndi6cN.js.map +1 -0
  70. package/dist/mosterdcomponents/format-BAfsQfy1.js.map +1 -0
  71. package/dist/mosterdcomponents/i18n-B1IIkRF9.js.map +1 -0
  72. package/dist/mosterdcomponents/index-AokUFVX0.js.map +1 -0
  73. package/dist/mosterdcomponents/index-CprJSlzK.js.map +1 -0
  74. package/dist/mosterdcomponents/index.esm.js +1 -1
  75. package/dist/mosterdcomponents/index.esm.js.map +1 -0
  76. package/dist/mosterdcomponents/mosterdcomponents.esm.js +1 -1
  77. package/dist/mosterdcomponents/mosterdcomponents.esm.js.map +1 -0
  78. package/dist/mosterdcomponents/p-aae8a9dc.entry.js +1 -0
  79. package/dist/mosterdcomponents/query-params-B1HfnMOl.js.map +1 -0
  80. package/dist/mosterdcomponents/quill-C9pgw_k-.js.map +1 -0
  81. package/dist/mosterdcomponents/validation-DbEViuiw.js.map +1 -0
  82. package/dist/types/components/documents/mrd-document-container/mrd-document-container.d.ts +6 -2
  83. package/dist/types/components/documents/mrd-document-view/mrd-document-view.d.ts +29 -1
  84. package/dist/types/components/documents/mrd-file-preview/file-preview-kind.d.ts +9 -0
  85. package/dist/types/components/documents/mrd-file-preview/mrd-file-preview.d.ts +41 -0
  86. package/dist/types/components/layout/mrd-layout-section/mrd-layout-section.d.ts +17 -1
  87. package/dist/types/components/table/mrd-table/mrd-table.d.ts +23 -0
  88. package/dist/types/components/table/mrd-table/virtual-scroll.d.ts +7 -0
  89. package/dist/types/components.d.ts +194 -7
  90. package/dist/types/types/client-layout.d.ts +10 -0
  91. package/package.json +1 -1
  92. package/dist/mosterdcomponents/p-9b3c0917.entry.js +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-DbEViuiw.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;;;;"}
@@ -1,5 +1,5 @@
1
1
  import { EventEmitter } from '../../../stencil-public-runtime';
2
- import { ClientArchetype, ClientLayoutItem } from '../../../types/client-layout';
2
+ import { ClientArchetype, ClientLayoutItem, ClientLayoutNavigateBehaviour } from '../../../types/client-layout';
3
3
  /**
4
4
  * Owns a document collection view: a single toolbar (view switch + collection
5
5
  * actions like "New folder", and — later — upload / drag-drop) plus the two
@@ -49,10 +49,14 @@ export declare class MrdDocumentContainer {
49
49
  qs: string;
50
50
  aggQs: string;
51
51
  }>;
52
- /** A row / document was activated. Host routes to the object page. */
52
+ /** A row / document was activated. Host routes to the object page. Documents
53
+ * are always the "quick look" use case, so navigateBehaviour is hardcoded
54
+ * to OVERLAY_PAGE here — unlike the generic VIEW/RELATED_VIEW table path in
55
+ * mrd-layout-section, which takes it from the item's configuration. */
53
56
  mrdNavigate: EventEmitter<{
54
57
  href?: string;
55
58
  label: string;
59
+ navigateBehaviour?: ClientLayoutNavigateBehaviour;
56
60
  }>;
57
61
  /** A table toolbar action was triggered. */
58
62
  mrdAction: EventEmitter<{
@@ -16,6 +16,15 @@ export declare class MrdDocumentView {
16
16
  /** The data record from the /data endpoint. Fields keyed by name; relations under `_links`. */
17
17
  data: Record<string, unknown>;
18
18
  locale: string;
19
+ /** Signed URL for the file's inline preview (mrd-file-preview), resolved by
20
+ * the host in response to mrdLoadPreview. Empty while unresolved — the
21
+ * preview area shows a loading state until the host injects a value. */
22
+ previewUrl: string;
23
+ /** Minimum height (px) of the inline preview area — it stretches to fill the
24
+ * available row height in the wide side-by-side layout (see mrd-document-view.scss),
25
+ * and falls back to this height when stacked. Overlay hosts typically pass a
26
+ * smaller value than the full-page default to fit available chrome. */
27
+ previewHeight: number;
19
28
  /** Navigate to the container (dossier). Host resolves the href and routes. */
20
29
  mrdNavigate: EventEmitter<{
21
30
  href?: string;
@@ -26,11 +35,30 @@ export declare class MrdDocumentView {
26
35
  href: string;
27
36
  fileName: string;
28
37
  }>;
38
+ /** The file slot has an href and needs a signed URL for inline preview.
39
+ * Fired once on load and again whenever the file href changes (e.g. the
40
+ * overlay is reused for a different document via prev/next). Host resolves
41
+ * it and calls back with `previewUrl` — the same pattern as mrdLoadImage /
42
+ * setImagePreview on mrd-layout-section. */
43
+ mrdLoadPreview: EventEmitter<{
44
+ href: string;
45
+ }>;
46
+ /** Tracks the href a preview was last requested for, so componentDidLoad and
47
+ * the data watcher don't emit duplicate requests for the same file. */
48
+ private lastPreviewHref;
49
+ componentDidLoad(): void;
50
+ dataChanged(): void;
51
+ private requestPreviewIfNeeded;
29
52
  /** Value of a value-slot: reads data[field] via the slot→field map. */
30
53
  private slotValue;
31
54
  /** Relation link for a relation-slot: reads data._links[field]. */
32
55
  private slotLink;
33
56
  private renderContainer;
34
- private renderFile;
57
+ /** Filename + download button — part of the metadata column, not the preview
58
+ * panel, so it stays next to the title/summary in the wide side-by-side layout. */
59
+ private renderFileMeta;
60
+ /** The preview panel itself (iframe/image/loading state) — its own grid
61
+ * column in the wide layout, so it can take the full available height. */
62
+ private renderPreviewPanel;
35
63
  render(): any;
36
64
  }
@@ -0,0 +1,9 @@
1
+ /** Pure classification logic for mrd-file-preview — no Stencil dependency. */
2
+ export type FilePreviewKind = 'pdf' | 'image' | 'unsupported';
3
+ /**
4
+ * Decide how to render a file given its declared mime type and/or file name.
5
+ * A declared mime type is authoritative when present (a mismatched file name
6
+ * extension is ignored); the file name extension is only consulted as a
7
+ * fallback when no mime type is known.
8
+ */
9
+ export declare function detectPreviewKind(mimeType?: string | null, fileName?: string | null): FilePreviewKind;
@@ -0,0 +1,41 @@
1
+ import { EventEmitter } from '../../../stencil-public-runtime';
2
+ /**
3
+ * Renders a signed URL inline as a PDF (native browser viewer, via `<iframe>`)
4
+ * or an image (`<img>`), picked from `mimeType`/`fileName`. Purely
5
+ * presentational: the signed URL is used directly as element `src` — a
6
+ * navigation, not a fetch/XHR, so no CORS handling is needed here. Fetching
7
+ * the signed URL itself is the host's responsibility, same as `mrdLoadImage` /
8
+ * `setImagePreview` on mrd-layout-section.
9
+ */
10
+ export declare class MrdFilePreview {
11
+ /** Signed URL to render. */
12
+ src: string;
13
+ /** Declared mime type (e.g. 'application/pdf', 'image/png'), when known.
14
+ * Authoritative over `fileName` when present. */
15
+ mimeType: string;
16
+ /** Original file name — used for extension-based detection when `mimeType`
17
+ * is absent, and as alt/title text. */
18
+ fileName: string;
19
+ /** The file's own reference href (not the signed preview URL in `src`).
20
+ * When set, an unsupported type falls back to the same download button
21
+ * used elsewhere in the library, so hosts need no new wiring. */
22
+ href: string;
23
+ locale: string;
24
+ /** The image failed to load — most likely an expired signed URL. Host
25
+ * should fetch a fresh signed URL and update `src`.
26
+ * Note: this is only raised for images. Browsers don't reliably surface
27
+ * HTTP-level failures (e.g. a 403 on an expired URL) through an iframe's
28
+ * load/error events, so the same detection isn't available for PDFs. */
29
+ mrdPreviewReload: EventEmitter<void>;
30
+ /** Download the file. Same shape as mrd-document-view / mrd-layout-section's
31
+ * mrdDownload — host resolves `href` to a signed URL. */
32
+ mrdDownload: EventEmitter<{
33
+ href: string;
34
+ fileName: string;
35
+ }>;
36
+ private imageFailed;
37
+ srcChanged(): void;
38
+ private onImageError;
39
+ private retry;
40
+ render(): any;
41
+ }
@@ -1,5 +1,5 @@
1
1
  import { EventEmitter } from '../../../stencil-public-runtime';
2
- import { ClientLayoutItem, ClientLayoutItemNavigate, ClientViewMetadata, ClientArchetype, RelationSearchResult } from '../../../types/client-layout';
2
+ import { ClientLayoutItem, ClientLayoutItemNavigate, ClientLayoutNavigateBehaviour, ClientViewMetadata, ClientArchetype, RelationSearchResult } from '../../../types/client-layout';
3
3
  import { DistinctValue } from '../../documents/mrd-document-list/folder-tree';
4
4
  export declare class MrdLayoutSection {
5
5
  el: HTMLElement;
@@ -17,16 +17,23 @@ export declare class MrdLayoutSection {
17
17
  /** Top-level archetypes on the object dashboard. When it contains commons.document,
18
18
  * the record is rendered as a single-document view instead of generic fields. */
19
19
  archetypes: ClientArchetype[];
20
+ /** Minimum height (px) of the commons.document inline file preview — it
21
+ * stretches taller in the wide side-by-side layout. Pass a smaller value
22
+ * when embedding the record in an overlay with limited height. */
23
+ documentPreviewHeight: number;
20
24
  private searchQueryMap;
21
25
  private searchResultsMap;
22
26
  private imagePreviewUrl;
23
27
  private imagePreviews;
24
28
  private openHistoryField;
29
+ /** Signed URL for the commons.document archetype's inline file preview. */
30
+ private documentPreviewUrl;
25
31
  private historyClickOutside;
26
32
  mrdNavigate: EventEmitter<{
27
33
  href?: string;
28
34
  label: string;
29
35
  navigate?: ClientLayoutItemNavigate;
36
+ navigateBehaviour?: ClientLayoutNavigateBehaviour;
30
37
  }>;
31
38
  mrdSearch: EventEmitter<{
32
39
  query: string;
@@ -51,6 +58,12 @@ export declare class MrdLayoutSection {
51
58
  fieldName: string;
52
59
  href: string;
53
60
  }>;
61
+ /** Re-emitted from an embedded mrd-document-view's mrdLoadPreview (commons.document
62
+ * single-object view); host resolves the file href to a signed URL and calls
63
+ * setDocumentPreviewUrl(). */
64
+ mrdLoadDocumentPreview: EventEmitter<{
65
+ href: string;
66
+ }>;
54
67
  /** Re-emitted from an embedded mrd-table's mrdAction; host builds the target URL from dataClass. */
55
68
  mrdViewAction: EventEmitter<{
56
69
  name: string;
@@ -125,6 +138,9 @@ export declare class MrdLayoutSection {
125
138
  setImagePreview(fieldName: string, url: string): Promise<void>;
126
139
  /** Open the lightbox directly with a URL (e.g. after mrdDownload on a FILE field). */
127
140
  openImagePreview(url: string): Promise<void>;
141
+ /** Provide a resolved signed URL for the commons.document archetype's inline
142
+ * file preview, in response to mrdLoadDocumentPreview. */
143
+ setDocumentPreviewUrl(url: string): Promise<void>;
128
144
  private resolveSearchKey;
129
145
  private handleViewLoadPage;
130
146
  private handleSearchInput;
@@ -5,6 +5,11 @@ export declare class MrdTable {
5
5
  el: HTMLElement;
6
6
  private pendingPages;
7
7
  private debounceTimer;
8
+ /** Timestamp of the last mrdLoadPage emission per outstanding page — drives stale-request detection. */
9
+ private requestedAt;
10
+ /** Retry count per page since it first became stale. */
11
+ private retryAttempts;
12
+ private staleCheckTimer;
8
13
  private outsideClickHandler;
9
14
  private keydownHandler;
10
15
  private createPickerClickHandler;
@@ -26,6 +31,9 @@ export declare class MrdTable {
26
31
  rowHeight: number;
27
32
  /** Height of the scroll container in px. */
28
33
  tableHeight: number;
34
+ /** Time (ms) to wait for setPage() before retrying a page request; after
35
+ * MAX_RETRY_ATTEMPTS retries the page is marked failed (see failedPages). */
36
+ requestTimeoutMs: number;
29
37
  /** Clamp renderEnd when totalElements shrinks (e.g. after a filter is applied). */
30
38
  totalElementsChanged(newVal: number): void;
31
39
  /** Reset to primary view when the item prop is replaced from outside. */
@@ -34,6 +42,8 @@ export declare class MrdTable {
34
42
  private activeViewIdx;
35
43
  loadedPages: Map<number, Record<string, any>[]>;
36
44
  requestedPages: Set<number>;
45
+ /** Pages that timed out MAX_RETRY_ATTEMPTS times — rendered as a retry row instead of shimmer. */
46
+ failedPages: Set<number>;
37
47
  renderStart: number;
38
48
  renderEnd: number;
39
49
  colWidths: number[];
@@ -78,6 +88,11 @@ export declare class MrdTable {
78
88
  path: string;
79
89
  qs: string;
80
90
  }>;
91
+ /** Fired when a page request timed out MAX_RETRY_ATTEMPTS times without setPage() being called.
92
+ * Purely informational — the table shows its own retry row regardless of whether a host listens. */
93
+ mrdPageError: EventEmitter<{
94
+ page: number;
95
+ }>;
81
96
  /** Fired when a data row is clicked. Detail is the full row object including _links. */
82
97
  mrdRowClick: EventEmitter<Record<string, any>>;
83
98
  /** Fired when a toolbar action button is clicked.
@@ -105,6 +120,7 @@ export declare class MrdTable {
105
120
  aggQs: string;
106
121
  }>;
107
122
  componentWillLoad(): void;
123
+ componentDidLoad(): void;
108
124
  private applyDefaultSort;
109
125
  /**
110
126
  * Initialise (or reset) the virtual scroll.
@@ -159,10 +175,17 @@ export declare class MrdTable {
159
175
  private resetPages;
160
176
  private handleSortClick;
161
177
  private applySort;
178
+ /** Emits mrdLoadPage for a page and records the request timestamp for stale-request detection. */
179
+ private emitLoadPage;
162
180
  private emitPagesForWindow;
163
181
  private getRow;
164
182
  private requestPagesForWindow;
165
183
  private flushPendingPages;
184
+ /** Scans outstanding requests for staleness: retries up to MAX_RETRY_ATTEMPTS times,
185
+ * then gives up and marks the page as failed (rendered as a retry row). */
186
+ private checkStalePages;
187
+ /** Manually retry a page the user gave up on (clicked the retry row). */
188
+ private retryPage;
166
189
  private handleScroll;
167
190
  private handleFilterToggle;
168
191
  private handleFilterOpen;
@@ -7,6 +7,10 @@ export declare const BUFFER = 10;
7
7
  /** Wait this long (ms) after the last scroll event before requesting pages,
8
8
  * so pages the user quickly scrolls past are skipped. */
9
9
  export declare const REQUEST_DEBOUNCE_MS = 150;
10
+ /** Default time (ms) to wait for setPage() before treating a request as stale and retrying. */
11
+ export declare const REQUEST_TIMEOUT_MS = 15000;
12
+ /** Max retries for a stale page request before giving up and showing a retry row. */
13
+ export declare const MAX_RETRY_ATTEMPTS = 3;
10
14
  export declare function visibleCount(tableHeight: number, rowHeight: number): number;
11
15
  /** Render window (with buffer) for the given scroll offset. */
12
16
  export declare function computeWindow(scrollTop: number, rowHeight: number, tableHeight: number, total: number): {
@@ -24,3 +28,6 @@ export declare function getRowFromPages(pages: Map<number, Record<string, any>[]
24
28
  export declare function computeEffectiveTotal(loadedPages: Map<number, Record<string, any>[]>, pageSize: number, baseTotal: number): number;
25
29
  /** True when some loaded page was short — the exact total is then known. */
26
30
  export declare function isTotalKnownFromPages(loadedPages: Map<number, Record<string, any>[]>, pageSize: number): boolean;
31
+ /** Pages whose request timestamp is older than timeoutMs — candidates for retry or failure.
32
+ * Caller is expected to already exclude pages present in loadedPages. */
33
+ export declare function getStalePages(requestedAt: Map<number, number>, now: number, timeoutMs: number): number[];